POJ_1185_状态压缩dp
http://poj.org/problem?id=1185
一次考虑两行,比一行略为复杂。sta保存每种状态炮兵位置,sum保存每种状态当行炮兵总数,a保存地形,dp[i][j][k]表示到第i行当前行j状态上一行k状态的最大炮兵数。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; //int main() //{ // int num = 0; // for(int i = 0;i <= (1<<10);i++) // { // if(i & (i<<2) || i & (i<<1)) continue; // num++; // } // printf("%d",num); //} int dp[105][65][65],a[105] = {0},n,m,sta[65],sum[65] = {0}; int main() { memset(dp,-1,sizeof(dp)); scanf("%d%d",&n,&m); getchar(); if(n == 0 && m == 0) { printf("0\n"); return 0; } for(int i = 0;i < n;i++) { char temp[15]; gets(temp); for(int j = 0;j < m;j++) { if(temp[j] == 'H') a[i] |= (1<<j); } } // for(int i = 0;i < n;i++) printf("%d\n",a[i]); int cnt = 0; for(int i = 0;i < (1<<m);i++) { if(i & (i<<2)) continue; if(i & (i<<1)) continue; sta[cnt] = i; int temp = i; while(temp) { sum[cnt] += temp%2; temp /= 2; } cnt++; } // for(int i = 0;i < cnt;i++) printf("%d %d\n",sta[i],sum[i]); for(int i = 0;i < cnt;i++) { if(a[0] & sta[i]) continue; dp[0][i][0] = sum[i]; } // for(int i = 0;i < cnt;i++) printf("%d\n",dp[0][i][0]); for(int i = 0;i < cnt;i++) { if(a[1] & sta[i]) continue; for(int j = 0;j < cnt;j++) { if(sta[i] & sta[j]) continue; dp[1][i][j] = max(dp[1][i][j],dp[0][j][0]+sum[i]); } } for(int i = 2;i < n;i++) { for(int j = 0;j < cnt;j++) { if(a[i] & sta[j]) continue; for(int k = 0;k < cnt;k++) { if(sta[j] & sta[k]) continue; for(int l = 0;l < cnt;l++) { if(sta[j] & sta[l]) continue; if(dp[i-1][k][l] == -1) continue; dp[i][j][k] = max(dp[i][j][k],dp[i-1][k][l]+sum[j]); } } } } // for(int i = 0;i < cnt;i++) // { // for(int j = 0;j < cnt;j++) printf("%d ",dp[n-1][i][j]); // printf("\n"); // } int ans = -1; for(int i = 0;i < cnt;i++) { for(int j = 0;j < cnt;j++) ans = max(ans,dp[n-1][i][j]); } printf("%d\n",ans); return 0; }