状态压缩DP...很简单了...一行最多10个...用1代表放炮兵..0代表不放...每行的状态最多1024种..并且还要合法..这样一来..一行的状态最多60种了...
能影响到当前行的只有上两行..所以用三维的DP...dp[t][x1][x2]....t代表哪一层了...x1代表上一层的状态..x2代表当前层的状态...
dp[t][x1][x2]= max ( dp[t-1][y][x1] + cnt[x2]) ...y是t-2层的状态...cnt是当前层状态的炮兵数,也就是1的数量...这里看出约束条件..就是状态x1,x2,y不能冲突...
Program:
#include<iostream> #include<cmath> #include<stack> #include<queue> #include<set> #include<algorithm> #include<stdio.h> #include<string.h> #define ll long long #define oo 1000000007 using namespace std; int n,m,a[105],anum; char arc[105][12]; int cnt[65],dp[105][65][65]; bool ok1(int x) // 判断当前状态是否合法 { int p,i; p=-10; while (x) { i++; if (x%2) { if (i-p<=2) return false; p=i; } x/=2; } return true; } bool ok2(int t,int x) //判断当前状态能否放在当前的图上 { int i; for (i=m;i>=1 && x;i--) { if (x%2 && arc[t][i]=='H') return false; x/=2; } return true; } bool ok3(int y,int x) //判断状态y在上,状态x在下,能否不冲突 { while (y && x) { if (y%2 && x%2) return false; y/=2; x/=2; } return true; } int main() { int i,t,j,x,ans; while (~scanf("%d%d",&n,&m)) { anum=0; a[0]=0; for (i=0;i<(1<<m);i++) if (ok1(i)) { a[++anum]=i; cnt[anum]=0; j=i; while (j) { j=j&(j-1); cnt[anum]++; } } for (i=0;i<=n;i++) gets(arc[i]+1); memset(dp,0,sizeof(dp)); for (i=1;i<=anum;i++) if (ok2(1,a[i])) dp[1][0][i]=cnt[i]; for (t=2;t<=n;t++) for (i=0;i<=anum;i++) if (ok2(t,a[i])) for (j=0;j<=anum;j++) if (ok2(t-1,a[j]) && ok3(a[j],a[i])) for (x=0;x<=anum;x++) if (dp[t][j][i]<dp[t-1][x][j]+cnt[i] && ok3(a[x],a[i])) dp[t][j][i]=dp[t-1][x][j]+cnt[i]; ans=0; for (i=0;i<=anum;i++) for (j=0;j<=anum;j++) if (ans<dp[n][i][j]) ans=dp[n][i][j]; printf("%d\n",ans); } return 0; }