这道题和炮兵阵地很像,不同的是炮兵阵地是每个炮兵不能相互干扰..这题是每个块不能有交集...处理起来稍微麻烦点...


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;
}