这道题和炮兵阵地很像,不同的是炮兵阵地是每个炮兵不能相互干扰..这题是每个块不能有交集...处理起来稍微麻烦点...
Program:
#include<iostream> #include<stdio.h> #include<string.h> #include<set> #include<algorithm> #include<cmath> #define oo 1000000007 #define ll long long #define pi acos(-1.0) #define MAXN 505 using namespace std; char s[105][10]; int n,m,dp[105][105][105],canuse[105],w[105],num; bool legal(int x) { int a[10],i,p=x; w[num+1]=0; for (i=1;i<=m;i++) w[num+1]+=p%2,p/=2; a[0]=0; for (i=1;i<=m;i++) { a[i]=x%2; x/=2; if (a[i]) { if (i-1<1 || i+1>m) return false; if (a[i-1]) return false; if (a[i-2]) return false; } } return true; } bool canput(int x,int r) { int i,a[10]; x=canuse[x]; memset(a,0,sizeof(a)); for (i=1;i<=m;i++) { if (x%2) { a[i-1]=a[i]=a[i+1]=1; if (s[r-1][i]=='#' || s[r+1][i]=='#') return false; } x/=2; } for (i=1;i<=m;i++) if (a[i] && s[r][i]=='#') return false; return true; } bool ok(int x,int y,int tp) { int i,s[2][10]; x=canuse[x],y=canuse[y]; if (tp==2) { while (x && y) { if (x%2 && y%2) return false; x/=2,y/=2; } return true; } memset(s,0,sizeof(s)); for (i=1;i<=m;i++) { if (x%2) s[1][i-1]++,s[1][i]++,s[1][i+1]++,s[0][i]++; if (y%2) s[0][i-1]++,s[0][i]++,s[0][i+1]++,s[1][i]++; x/=2,y/=2; } for (i=1;i<=m;i++) if (s[1][i]>1 || s[0][i]>1) return false; return true; } int main() { int t,i,j,x,r,ans; scanf("%d",&t); while (t--) { scanf("%d%d",&n,&m); for (i=1;i<=n;i++) scanf("%s",s[i]+1); num=0; for (i=0;i<(1<<m);i++) if (legal(i)) canuse[++num]=i; memset(dp,0,sizeof(dp)); for (r=2;r<n;r++) for (i=1;i<=num;i++) if (canput(i,r)) for (j=1;j<=num;j++) if (ok(i,j,1)) for (x=1;x<=num;x++) if (ok(i,x,2)) dp[r][j][i]=max(dp[r][j][i],dp[r-1][x][j]+w[i]); ans=0; for (i=1;i<=num;i++) for (j=1;j<=num;j++) ans=max(ans,dp[n-1][i][j]); printf("%d\n",ans); } return 0; }