Problem Description Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns, each representing a street or a piece of wall. |
Input The input file contains one or more map descriptions, followed by a line containing the number 0 that signals the end of the file. Each map description begins with a line containing a positive integer n that is the size of the city; n will be at most 4. The next n lines each describe one row of the map, with a '.' indicating an open space and an uppercase 'X' indicating a wall. There are no spaces in the input file. |
Output For each test case, output one line containing the maximum number of blockhouses that can be placed in the city in a legal configuration.
Sample Input 4 .X.. .... XX.. .... 2 XX .X 3 .X. X.X .X. 3 ... .XX .XX 4 .... .... .... .... 0
Sample Output 5 1 5 2 4
|
题目分析:
同一行和同一列不能有两个碉堡(碉堡用 O 表示),除非他们之间存在墙(用 X 表示),有点类似于N皇后问题。
但该题就是一个经典的dfs问题,采用逐行搜索,从第一行开始从左往右依次进行搜索,每一个块都尝试能否放置碉堡,
然后用一个legal函数判断该块的左边和上边的块是否符合条件
代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int res,n;
char map[4][4];
int legal(int x,int y)
{
for(int a=y-1;a>=0;a--) //向左搜索
{
if(map[x][a]=='X') break;
if(map[x][a]=='O') return false;
}
for(int a=x-1;a>=0;a--) //向上搜索
{
if(map[a][y]=='X') break;
if(map[a][y]=='O') return false;
}
return true;
}
//逐行进行搜索
void dfs(int x,int y,int z)
{
if(x==n && y==0)
{
res=max(res,z);
return ;
}
if(y==n)
{
dfs(x+1,0,z);
return ;
}
// for(int i=0;i<n;i++)
for(int i=y;i<n;i++) //注意逐行搜索从左到右,y坐标要继承上一次的位置
{
if(map[x][i]=='.' && legal(x,i))
{
map[x][i]='O';
dfs(x,i+1,z+1);
map[x][i]='.';
}
}
dfs(x+1,0,z); //移到下一行
}
int main()
{
while(~scanf("%d",&n),n)
{
res=0;
for(int i=0;i<n;i++){
getchar(); //吸收
for(int j=0;j<n;j++){
scanf("%c",&map[i][j]);
}
}
dfs(0,0,0);
printf("%d\n",res);
}
return 0;
}
注意:
1. 由于前面的scanf()在读取输入时会在缓冲区中留下一个字符'\n'(输入完s[i]的值后按回车键所致)
所以要在生成map的两个for之间使用getchar()来清除缓冲区
2. dfs中的for循环 i=y 开始