P2704 炮兵阵地
phmaprostrate · · 个人记录
分析
一看就是状压DP,别问我为啥。这次的状压比较猛,它需要考虑
设计
这样我们就可以可以开心的预处理了。
1.预处理第一层状态,有其他状压类似,i << 1 & i 判断相邻位以为是否都有
1.状态本身合法。
2.不与第
3.不与地图冲突,(放山地啊?
最后,运算时,分别枚举
#include<iostream>
using namespace std;
const int N = 102,M = 11,S = 1 << M;
int so[S];
int Map[N];
bool can[S];
bool check(int ss){
if((((ss << 1) & ss) == 0) &&(((ss << 2) & ss) == 0)) return true;
else return false;
}
int n,m;
int dp[2][S][S];
int main(){
cin >> n >>m;
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
char x;
cin >> x;
Map[i] = (Map[i] << 1) + ( x == 'P');
}
}
int statem = (1 << m) - 1;
for(int i = 0;i <= statem;i++){
int x = i;
while(x){
so[i]++;
x = (x - 1) & x;
}
}
for(int i = 0;i <= statem;i++){
if(check(i)) can[i] = true;
}
for(int i = 0;i <= statem;i++){
if(can[i] && ((Map[1] & i) == i)) dp[0][0][i] = so[i];
}
for(int i = 0;i <= statem;i++){
if(can[i]){
for(int j = 0;j <= statem;j++){
if(!can[j] || (i & j) || ((Map[2] & j) != j)) continue;
dp[1][i][j] = max(dp[0][0][i] + so[j],dp[1][i][j]);
}
}
}
int flag = 0;
for(int i = 3;i <= n ;i++){
for(int j = 0;j <= statem;j++){
if(can[j] && ((Map[i] & j) == j)){
for(int s = 0;s <= statem;s++){
if(!can[s]) continue;
for(int u = 0;u <= statem;u++){
if(!can[u] || (u & s) || (u & j) || (j & s)) continue;
dp[flag][s][j] = max(dp[flag][s][j],dp[flag ^ 1][s] + so[j]);
}
}
}
}
flag = flag ^ 1;
}
int ans = 0;
for(int u = 0;u <= statem;u++){
for(int j = 0;j <= statem;j++){
ans = max(ans,dp[flag ^ 1][u][j]);
}
}
cout<<ans;
return 0;
}