搜索算法也算是一种暴力枚举策略,但是其算法特性决定了效率比直接的枚举所有答案要高,因为搜索可以跳过一些无效状态,降低问题规模。
题目来源 八皇后 Checker Challenge
题目描述
使用二维数组建图的话会增加搜索的操作,占用更大的空间。这里可以使用通过发现规律来降维的思想,具体如下
初始图形
初始图形中第一个皇后坐标为(1,2),对于其所有在主对角线平行的共线皇后为(2,3),(3,4),(4,5),(5,6),其规律是总有横坐标与纵坐标之差为与皇后所在位置相同;同理副对角线平行的皇后所在位置都有坐标与皇后所在位置横纵坐标之和相同。基于此,使用数组lx表示标记副对角线状态的数组,数组rx表示标记主对角线的数组。则有:
lx[x+y]=1;rx[x-y]=1;
来分别表示当前(x,y)的左斜和右斜是否有皇后。但问题是x-y可能为负数,数组下标不能为负数。这里可以使用加一个常量的方式,因为加个常量相对位置不会发生变化,值得注意的是,加常量之后对应数组大小也应该调整,否则会越界。
给出AC代码:
#include<iostream>
using namespace std;
int col[105],lx[105],rx[105], ans[105],n,cnt=0;//col代表列,lx代表左斜,rx代表右斜
void print(){
if(cnt<=2){
for(int i=1;i<=n;i++)
cout<<ans[i]<<" ";
cout<<endl;
}
cnt++;
}
void dfs(int k){
if(k>n) {
print();
return;
}
else{
for(int i=1;i<=n;i++){
if(!col[i]&&!lx[k+i]&&!rx[k-i+n]){
//做占用操作
ans[k]=i;
col[i]=1;
lx[k+i]=1;
rx[k-i+n]=1;//防止出现负数
dfs(k+1);//下一行
//做回溯
col[i]=0;
lx[i+k]=0;
rx[k-i+n]=0;
}
}
}
}
int main(){
cin>>n;
dfs(1);
cout<<cnt<<endl;
return 0;
}
使用k来表示当前到哪一列了,dfs()不代表深度优先搜索,对于搜索问题来讲,dfs作函数名似乎是做题家的共识。
题解参考https://www.luogu.com.cn/blog/kiroto/solution-p1218