这是一道N皇后问题的小变种。我在编写的过程中开始遇到的困难:由于地图上可能有墙(‘X’),所以每一行和每一列不一定只能放一个机关枪,问题出来了,N后问题是每搜索一行都要去搜索下一行,但是这道题目不能这么做,因为这一行可能还能继续放。所以,递归函数的参数应该有2个------一个记录行下标,一个记录列下标。因此,搜索行需要递归,搜索列同样也要递归。
行的递归:for(j=m; j<=n; j++)
{
if(map[x][j]=='.' && satisfied(x, j))
{
map[x][j] = 'E';
max_sum++;
DFS(x,j+1);//这就是行的递归
map[x][j] = '.';
max_sum--;
}
}当然,行递归完之后就是列的递归了:DFS(x+1,1);
同时,航宇列递归完了都要有其相应的出口:
if(x>n) 行递归出口
{
if(sum<=max_sum)
sum = max_sum;
return ;
}
if(m>n) 列递归出口
{
if(sum<=max_sum)
sum = max_sum;
DFS(x+1,1);
return ;
}
AC源代码:
#include <iostream>
using namespace std;
char map[5][5];
int n, max_sum, sum;bool satisfied(int x, int y)
{
int i, j;
bool flagRowLeft ,flagRowRight ,flagLineUp,flagLineDown;
flagRowLeft = flagRowRight = flagLineUp= flagLineDown =false;
for(j=y; j>=1; j--)
{
if(map[x][j]=='E')
{
flagRowLeft = false;
break;
}
if(map[x][j]=='X')
{
flagRowLeft = true;
break;
}
}
if(j==0)
flagRowLeft = true;
for(j=y; j<=n; j++)
{
if(map[x][j]=='E')
{
flagRowRight = false;
break;
}
if(map[x][j]=='X')
{
flagRowRight = true;
break;
}
}
if(j==n+1)
flagRowRight = true;for(i=x; i>=1; i--)
{
if(map[i][y]=='E')
{
flagLineUp = false;
break;
}
if(map[i][y]=='X')
{
flagLineUp = true;
break;
}
}
if(i==0)
flagLineUp = true;
for(i=x; i<=n; i++)
{
if(map[i][y]=='E')
{
flagLineDown = false;
break;
}
if(map[i][y]=='X')
{
flagLineDown = true;
break;
}
}
if(i==n+1)
flagLineDown = true;if(flagRowLeft && flagRowRight && flagLineUp && flagLineDown)
return true;
return false;
}
void DFS(int x, int m)
{
int i, j, k;
if(x>n)
{
if(sum<=max_sum)
sum = max_sum;
return ;
}
if(m>n)
{
if(sum<=max_sum)
sum = max_sum;
DFS(x+1,1);
return ;
}
for(j=m; j<=n; j++)
{
if(map[x][j]=='.' && satisfied(x, j))
{
map[x][j] = 'E';
max_sum++;
DFS(x,j+1);
map[x][j] = '.';
max_sum--;
}
}
DFS(x+1,1);
}void main()
{
int i, j;
while(cin>>n&& n)
{
max_sum = 0;
sum=0;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
cin>>map[i][j];
DFS(1, 1);
cout<<sum<<endl;
}
}
![]()