题目大意:在图上放置炮台,并且炮台之间不能相互威胁(即两个炮台不能中间无阻碍地放置在同行或同列),个人感觉有点像N皇后的问题,只不过进阶的东西就是多了墙
解题思路:做这题时想起了当时做N皇后的解法,只不过多了一步遇到墙壁就停止,不过发现在你不放在这个位置时,准备回溯你要把之前标记的行和列全部清空,问题就来了,如果你在清空标记时遇到有一格同时被两个炮台标记怎么办,这时就换种思路,即你每当要放炮台时沿着四个方向找有没有炮台,有就不能放,没有就放;其实上面那个做法可以用一个二层数组标记,只不过可能会比较麻烦
15ms代码如下,可能还可以优化,暂时没想到:
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
char map[10][10];
int book[10][10],n,m,MAX,xia[4][2]={0,1,1,0,0,-1,-1,0};
bool pan(int x,int y) //判断坐标是否遇到墙壁或者越界
{
if(map[x][y]=='X' || x<0|| x>=n || y<0 || y>=m)
return false;
return true;
}
bool cr(int i,int x,int y) //沿着第i个方向一直查询如果遇到炮台返回真否则假即该方向符合条件
{
if(pan(x,y))
{
if(!book[x][y])
return cr(i,x+xia[i][0],y+xia[i][1]);
else
return true;
}
return false;
}
bool find(int x,int y) //查询四个方向
{
if(cr(0,x,y)||cr(1,x,y)||cr(2,x,y)||cr(3,x,y))
return false;
return true;
}
void dfs(int k)
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
if(pan(i,j) && find(i,j) && !book[i][j]) //该节点四个方向无障碍 并且没被放过
{
if(k+1>MAX) //更新数据(为什么不能是直接最大值+1呢?因为该位置存在着放和不放 有点像01背包,要整体最优)
MAX=k+1;
book[i][j]=1;
dfs(k+1);
book[i][j]=0; //回溯
}
}
return ;
}
int main()
{
int i,j;
while(~scanf("%d",&n) && n)
{
m=n;
MAX=0;
getchar();
for(i=0;i<n;i++)
scanf("%s",map[i]);
memset(book,0,sizeof(book));
dfs(0);
printf("%d\n",MAX);
}
return 0;
}