枚举每个可以放的位置 是放还是不放 然后判断合法的方法能放多少个 比较保存最大的一个 0.029s
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
int T;
while(scanf("%d",&T)&&T)
{
char G[T+2][T+2];
int vis[T+2][T+2];
memset(G,0,sizeof(G));
memset(vis,0,sizeof(vis));
for(int i = 1; i <= T; i++)///存图
{
getchar();
for(int j = 1; j <= T; j++)
scanf("%c",&G[i][j]);
}
int N = 1;
for(int i = 0; i < T*T; i++)///枚举的最大次数
N *= 2;
int MAX = 0;
for(int i = 0 ;i < N; i++)
{
int t = i,f[T+2][T+2],sum = 0;///sum 计算放的个数
for(int x = 1; x <= T; x++)
for(int y = 1; y <= T; y++)
{
if(t%2 == 1)sum++;
f[x][y] = t%2;
if(G[x][y] == 'X')///表示石墙
{
if(f[x][y] == 1)sum--;
f[x][y] = -1;
}
t /= 2;
}
if(sum <= MAX)continue;
int ok = 1;
for(int x = 1; x <= T && ok; x++)///判断冲突的好像可以有更简洁的
{
for(int y = 1; y <= T && ok; y++)
{
if(f[x][y] != 1)continue;
for(int r = x+1; r <= T && ok; r++)///判断行是否冲突
{
int flag = 0;
for(int l = x+1;l <= r; l++)///x 到r之间是否有墙隔着
if(f[l][y] == -1)flag = 1;
if(f[x][y] == f[r][y] && f[x][y] == 1 && !flag)
ok = 0;
}
for(int c = y+1; c <= T && ok; c++)///判断列是否冲突
{
int flag = 0;
for(int l = y+1; l <= c; l++)
if(f[x][l] == -1)flag = 1;
if(f[x][y] == f[x][c] && f[x][y] == 1 && !flag)
ok = 0;
}
}
}
if(ok == 1)
MAX = sum;
}
printf("%d\n",MAX);
}
return 0;
}
回溯 DFS判断每个位置 每个位置有3两种方法 放或者不放 不合法的情况就退回上一层 否者继续递归下去 直到判断每一个是放还是不放