小H的塔防游戏2
题目描述
小H在你的帮助下成功通过了塔防游戏1.
现在来到了第二关,有一个n*n的地图,地图中'X'代表障碍物,'.'代表空地.
小H需要在空地上建防御塔,规定任意两个防御塔不能位于同一行或者同一列,除非它们之间有障碍物
请你帮助小H计算最多能建多少个防御塔
输入
第一行一个n(2<=n<=4),表示地图的大小
4*4的矩形,矩形的每个元素为'X'或'.',分别表示障碍物和空地
输出
输出防御塔的最大个数
输入样例:
4
.X..
....
XX..
....
输出样例:
5
题目分析:
这题与n皇后问题类似,只是除去了同一对角线的限制,并增加了障碍物。同样我们可以按照行来分析。从第一行开始,将防御塔放在某一个空地,并判断该行其他位置是否可以放置防御塔,之后逐层以同样的方式进行遍历,并在遍历同一层的下一个情况之前还原现场。同样可设置一个全局变量,通过比较赋值最大的防御塔数量。
解决方案
#include <iostream>
#include <vector>
using namespace std;
vector<int>x,y; //记录防御塔的位置
char graph[4][4];
int n,maximun=0;
bool check(int x1,int y1){
for(int i=0;i<x.size();i++){ //对每一个同行或同列的点进行判断
if(x1==x[i]){
bool flag=false;
for(int j=min(y1,y[i])+1;j<max(y1,y[i]);j++)
if(graph[x1][j]=='X')
flag=true;
if(!flag)
return flag;
}
if(y1==y[i]){
bool flag=false;
for(int j=min(x1,x[i])+1;j<max(x1,x[i]);j++)
if(graph[y1][j]=='X')
flag=true;
if(!flag)
return flag;
}
}
return true; //该位置与其他防御塔所在位置均不相互影响
}
void restore(int row){ //还原现场,以行为单位进行删除
for(int i=x.size()-1;i>=0;i--){
if(x[i]==row){
x.erase(x.begin()+i);
y.erase(y.begin()+i);
}
}
}
void seek(int row){
if(row==n){ //每一行均已遍历完
int k=x.size(); //防御塔个数
maximun=max(maximun,k);
return;
}
for(int i=0;i<n;i++){
if(graph[row][i]=='.'&&check(row,i)){ //该行某一个点可放置防御塔
x.push_back(row);
y.push_back(i);
for(int j=0;j<n;j++)
if(graph[row][j]=='.'&&check(row,j)&&j!=i){ //判断该行其他点
x.push_back(row);
y.push_back(j);
}
seek(row+1); //逐层向下遍历
restore(row); //还原现场
}
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>graph[i][j];
seek(0);
cout<<maximun;
return 0;
}