题目链接:
https://vjudge.net/contest/159644#problem/B
题意:
在一个N*M的矩阵上布置炮兵部队,只有平原可以布置,然后每个炮兵部队都有一个攻击范围,它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。
问最多可以安排几个炮兵
题解:
http://www.cnblogs.com/buptLizer/archive/2012/08/23/2651881.html
状压dp
dp[i][j][k]:=考虑到第i行, 这一行是第i个合法状态,上一行是第j个合法状态,最多可以安排的炮兵
转移:dp[i][j][k] = max(dp[i][j][k],dp[i-1][k][p]+num[j]); num[j]表示j这个合法状态可以安排的炮兵数
代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 typedef long long ll; 6 #define MS(a) memset(a,0,sizeof(a)) 7 #define MP make_pair 8 #define PB push_back 9 const int INF = 0x3f3f3f3f; 10 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 11 inline ll read(){ 12 ll x=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 ////////////////////////////////////////////////////////////////////////// 18 const int maxn = 80+10; 19 20 int dp[105][maxn][maxn]; 21 int state[maxn],num[maxn],cnt; 22 int cur[105]; 23 char mp[105][20]; 24 int n,m; 25 26 int getnum(int x){ 27 int res = 0; 28 while(x){ 29 res += (x&1); 30 x = x>>1; 31 } 32 return res; 33 } 34 35 void init(){ 36 cnt = 0; 37 for(int i=0; i<(1<<m); i++){ 38 if(!(i&(i<<1)) && !(i&(i<<2))){ 39 state[cnt] = i; 40 num[cnt] = getnum(i); 41 cnt++; 42 } 43 } 44 } 45 46 int main(){ 47 cin >> n >> m; 48 for(int i=0; i<n; i++){ 49 cin >> mp[i]; 50 for(int j=0; j<m; j++){ 51 if(mp[i][j] == 'P') 52 cur[i] += (1<<(m-j-1)); 53 } 54 } 55 56 memset(dp,-1,sizeof(dp)); 57 init(); 58 for(int i=0; i<cnt; i++) 59 if(!(state[i]&(~cur[0]))) // 如果与能放炮兵的反有交集 就不可行 60 dp[0][i][0] = num[i]; 61 for(int i=1; i<n; i++){ 62 for(int j=0; j<cnt; j++){ 63 if((~cur[i])&state[j]) continue; 64 for(int k=0; k<cnt; k++){ 65 if((~cur[i-1])&state[k]) continue; 66 if(state[j]&state[k]) continue; 67 for(int p=0; p<cnt; p++){ 68 if(i>=2 && ((~cur[i-2])&state[p])) continue; 69 if(state[j]&state[p]) continue; 70 if(dp[i-1][k][p] == -1) continue; 71 dp[i][j][k] = max(dp[i][j][k],dp[i-1][k][p]+num[j]); 72 } 73 } 74 } 75 } 76 77 int ans = 0; 78 for(int i=0; i<cnt; i++) 79 for(int j=0; j<cnt; j++) 80 ans = max(ans,dp[n-1][i][j]); 81 cout << ans << endl; 82 83 return 0; 84 } 85 86 // http://www.cnblogs.com/buptLizer/archive/2012/08/23/2651881.html