題意是有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--;
}
}