题目描述
监狱的每间牢房是一个不超过4×4的正方形,里面设有一些障碍,牢房里住着的犯人脾气都很大,只要两个犯人位于同一行或同一列即会发生冲突,但障碍物可以阻挡同行或同列犯人的冲突。问最多可放几个犯人而不会发生冲突。如下图所示,左边表示初始牢房样,右边4个显示了摆放方案,当然,最后两个方案是错误的。
输入
有多组测试数据,每组数据第一行为一个整数N表示牢房大小。随后N行描述牢房,其中X表示障碍。
所有测试数据结束的标志为0。
输出
输出最多可放的犯人数。
样例输入 Copy
4
.X…
…
XX…
…
2
XX
.X
3
.X.
X.X
.X.
3
…
.XX
.XX
4
…
…
…
…
0
样例输出 Copy
5
1
5
2
4
解析:
分为两种讨论
第一种:我们不放囚犯 dfs(p+1,cnt)
第二种:我们放囚犯,但是要去遍历一下这个点四周在没有阻碍物的情况下有没有其他和他在一行或者在一列,这种是不可取的。
如果我们在这个点放了,要给这个点标记,再去递归。
#include<bits/stdc++.h>
using namespace std;
int n;
char s[1005][1005];
int maxn;
void dfs(int p,int cnt)
{
if(p==n*n)
{
maxn=max(maxn,cnt);
return ;
}
int x=p/n;int y=p%n;
dfs(p+1,cnt);//这个是我不放囚犯的
if(s[x][y]=='.') //这边暴力遍历看看有没有不符合条件的
{
int op=1;
for(int i=x;i<n;i++)
{
if(s[i][y]=='X') break;
if(s[i][y]=='Q') op=0;
}
for(int i=x;i>=0;i--)
{
if(s[i][y]=='X') break;
if(s[i][y]=='Q') op=0;
}
for(int i=y;i<n;i++)
{
if(s[x][i]=='X') break;
if(s[x][i]=='Q') op=0;
}
for(int i=y;i>=0;i--)
{
if(s[x][i]=='X') break;
if(s[x][i]=='Q') op=0;
}
if(op==1) //如果op还是1的话,说明可以放囚犯
{
s[x][y]='Q'; //犯了囚犯给他标记一下,下一次不能在放在这里
dfs(p+1,cnt+1);//递归到下一层
s[x][y]='.'; //恢复现场
}
}
}
int main()
{
while(~scanf("%d",&n)&&n)
{
maxn=0;
for(int i=0;i<n;i++) cin>>s[i];
dfs(0,0);
cout<<maxn<<endl;
}
}