题解:UVA11214 守卫键盘 Guarding the Chessboard
题意:输入一个 棋盘,某些格子有标记。用最少的皇后守卫(即占据或者攻击)所有带标记的格子。
分析:因为不知道放几个皇后可以守卫所有带标记的格子,即回溯法求解时解答树的深度没有明显的上限,所以使用迭代加深搜索。
将棋盘的每个格子标记为 ,依次枚举守卫的皇后个数,枚举当前守卫的皇后个数下所有的放置情况,看是否能全部守卫。(枚举方式: 枚举 , 枚举 )
AC code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1005;
string s[maxn];
int vis[maxn][maxn];
int v[maxn][maxn];
int t;
int n,m;
bool check(){
for(int i=0;i<n;i++){//判断所有被标记的正方形是否被保护
for(int j=0;j<m;j++){
if(v[i][j]&&!vis[0][i]&&!vis[1][j]&&!vis[2][j+i]&&!vis[3][j-i+n])
return 0;
}
}
return 1;
}
bool dfs(int cur,int pos,int tot){
if(cur==tot){//放置tot个皇后是否可全保护
if(check()){
cout<<"Case "<<t<<": "<<tot<<endl;
return 1;
}
return 0;
}
for(int i=pos;i<=n*m;i++){//所有点被标记成0~n*m-1
int x=i/m;//当前位置的横坐标
int y=i%m;
int tmp1=vis[0][x];
int tmp2=vis[1][y];
int tmp3=vis[2][x+y];
int tmp4=vis[3][y-x+n];
vis[0][x]=vis[1][y]=vis[2][x+y]=vis[3][y-x+n]=1;
if(dfs(cur+1,i+1,tot)){
return 1;//此处优化,i+1下次枚举是当前位置再加1,避免情况重复
}
vis[0][x]=tmp1;
vis[1][y]=tmp2;
vis[2][x+y]=tmp3;
vis[3][y-x+n]=tmp4;
}
return 0;//枚举当前所有情况不满足
}
signed main(){
while(cin>>n){
if(n==0){
break;
}
t++;
cin>>m;
memset(v,0,sizeof(v));
for(int i=0;i<n;i++){
cin>>s[i];
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(s[i][j]=='X'){
v[i][j]=1;
}
}
}
for(int i=0;;i++){
memset(vis,0,sizeof(vis));
if(dfs(0,0,i)){
break;
}
}
}
return 0;
}
本人(KK_SpongeBob)蒟蒻,写不出好文章,但转载请注明原文链接:https://www.cnblogs.com/OIer-QAQ/p/18575249

浙公网安备 33010602011771号