dp[i][j][k] 表示前i行 在i-1为j 的状态下 第i行为k的状态下 最多能放多少 多少炮台。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; int dp[100][60][60],st[60],sum[60],a[100]; int n,m,cnt; int get(int x)//处理出x状态下 能放下的炮台数 就是二进制下的1的数量 { int s=0; while(x) { if(x&1)s++; x>>=1; } return s; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { cnt=0; for(int i=0;i<n;i++) { char str[100]; a[i]=0; scanf("%s",str); for(int j=0;j<m;j++) { if(str[j]==‘H‘)a[i]|=(1<<j); } } memset(dp,-1,sizeof dp); int tmp=1<<m; for(int i=0;i<tmp;i++)//拿出有用的状态 { if((!(i&(i<<1))) && (!(i&(i<<2)))) { st[cnt]=i; sum[cnt++]=get(i); } } for(int i=0;i<cnt;i++)//处理第一行 { if(!(a[0]&st[i])) { dp[0][0][i]=sum[i]; } } for(int i=1;i<n;i++) { for(int j=0;j<cnt;j++)//枚举当前行的状态 { if(!(st[j]&a[i]))//如果这个状态和地图不冲突 { for(int k=0;k<cnt;k++)//枚举i-1行的状态 { if(!(st[k]&st[j]))//如果i-1行的状态和i行的状态不冲突 { for(int p=0;p<cnt;p++)//i-2 { if(!(st[j]&st[p]))//如果i-2行的状态和第i行的状态不冲突 { if(dp[i-1][p][k]!=-1)//如果之前的状态合法才能转移 { dp[i][k][j]=max(dp[i][k][j],dp[i-1][p][k]+sum[j]); } } } } } } } } int ans=0; 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; }
原文:http://blog.csdn.net/u010709592/article/details/19053921