题意是有n*n大小的地图,地图上点(.)代表空地,X代表防火墙,在地图上放置碉堡,碉堡可以横向或者竖向扫射,所以同一行或列上只能有一个碉堡,但是防火墙可以阻拦攻击,求最大能放置多少碉堡
// HDOJ1042 fire net
// 思维是主要靠深搜
#include <iostream>
using namespace std;
int visit[5][5]; // visit数组是用来存放状态的,0代表空地,1代表放了碉堡,2代表防火墙
int mmax, n, cnt;
bool ffind(int x, int y); // 判断当前位置是否可以放碉堡
void dfs();
int main()
{
char str[10];
while(cin >> n && n)
{
for(int i = 1; i <= n; i++)
{
cin >> str;
for(int j = 0; j < n; j++)
visit[i][j + 1] = (str[j] == 'X' ? 2 : 0);
}
cnt = mmax = 0;
dfs();
cout << mmax << endl;
}
return 0;
}
bool ffind(int x, int y)
{
// 从(x, y)点开始上下左右判断,如果遇到碉堡就返回false,如果遇到墙就结束本次循环
for(int i = y; i >= 1; i--)
{
if(visit[x][i] == 1)
return false;
if(visit[x][i] == 2)
break;
}
for(int i = y; i <= n; i++)
{
if(visit[x][i] == 1)
return false;
if(visit[x][i] == 2)
break;
}
for(int i = x; i >= 1; i--)
{
if(visit[i][y] == 1)
return false;
if(visit[i][y] == 2)
break;
}
for(int i = x; i <= n; i++)
{
if(visit[i][y] == 1)
return false;
if(visit[i][y] == 2)
break;
}
return true;
}
void dfs()
{
// 一列一列的深搜,如果发现一点能放碉堡就令状态数组变为1,表示放置碉堡
// 然后继续往下搜索,放置一个碉堡就领cnt计数器自增
// 如果搜索完整个,就跳出本次循环,将碉堡重新设置为空地
if(cnt > mmax)
mmax = cnt;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(!visit[i][j] && ffind(i,j))
{
visit[i][j] = 1;
cnt++;
// cout << "in" << endl; // 测试用
dfs();
// cout << "out" << endl; // 测试用
visit[i][j] = 0;
cnt--;
}
}