由于一个炮能影响的范围最多到下两行...所以两行两行来DP..而两行的情况直接搜出来..由于n可能是奇数..为了处理方便..n为奇数时..加一行全0的..把n变为偶数...
数据太弱..自己出了个100*10的全1输入来跑...N久才出来..真正完美的解法还是应该用状态压缩DP...
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; struct node { int h[33][2],num; }a[4005],p; int n,m,anum,pre[2][4005],prenum; int arc[105][12]; int dp[2][4005],ans; void dfs(int y,int x) { int i,j; for (i=1;i<=p.num;i++) if (abs(y-p.h[i][0])+abs(x-p.h[i][1])==2) return; p.num++; p.h[p.num][0]=y; p.h[p.num][1]=x; a[++anum]=p; for (j=x+1;j<=m;j++) dfs(y,j); for (i=y+1;i<=2;i++) for (j=1;j<=m;j++) dfs(i,j); p.num--; return; } void prework() { int i,j; anum=0; p.num=0; a[++anum]=p; for (i=1;i<=2;i++) for (j=1;j<=m;j++) dfs(i,j); return; } bool ok(int p,int t) // 判断当前状态适合当前图否 { int i; for (i=1;i<=a[p].num;i++) if (arc[t+a[p].h[i][0]-1][a[p].h[i][1]]==0) return false; return true; } bool f(int p1,int p2) // 判断状态间冲突否 { int i,j; for (i=1;i<=a[p1].num;i++) for (j=1;j<=a[p2].num;j++) if (abs(a[p1].h[i][0]-a[p2].h[j][0]-2)+abs(a[p1].h[i][1]-a[p2].h[j][1])==2) return false; return true; } int main() { int i,jj,j,t,k,mm; while (~scanf("%d%d",&n,&m)) { prework(); for (i=1;i<=n;i++) for (j=1;j<=m;j++) scanf("%d",&arc[i][j]); if (n%2) { n++; for (j=1;j<=m;j++) arc[n][j]=0; } mm=k=0; for (i=1;i<=anum;i++) if (ok(i,1)) { dp[k][i]=a[i].num; pre[k][++mm]=i; } prenum=mm; for (t=3;t<=n;t+=2) { k=1-k; memset(dp[k],0,sizeof(dp[k])); mm=0; for (i=1;i<=anum;i++) if (ok(i,t)) { pre[k][++mm]=i; for (jj=1;jj<=prenum;jj++) { j=pre[1-k][jj]; if (dp[k][i]<dp[1-k][j]+a[i].num && f(j,i)) dp[k][i]=dp[1-k][j]+a[i].num; } } prenum=mm; } ans=0; for (i=1;i<=anum;i++) if (dp[k][i]>ans) ans=dp[k][i]; printf("%d\n",ans); } return 0; }