DFS
- 一开始考虑用bool标记,但是每次清除标记就会很麻烦,
- 因为bool只有true和false,而一个位置可能被多次标记
- 所以用int型作为标记
- 注意访问一定要判断一下,避免越界导致出错
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int chess[8][8];//标记
string ans[93];//答案
int k=0;
void getans(string s,int pos){//已经排列坐标、查找行数
if(pos==8){
ans[k++].insert(0,s);//成功排列
return ;
}
for(int i=0;i<8;i++){//遍历pos这一行
if(chess[pos][i]==0){//未被访问
for(int j=pos+1;j<8;j++){//只考虑高于pos行的标记
chess[j][i]++;//纵向
if(j+i-pos>=0&&j+i-pos<=7)chess[j][j+i-pos]++;//左上对角
if(pos+i-j>=0&&pos+i-j<=7)chess[j][pos+i-j]++;//右上对角
}
char x=i+'1';
string next(s);
next.insert(next.end(),1,x);
getans(next,pos+1);//递归
for(int j=pos+1;j<8;j++){//清除本次标记
chess[j][i]--;
if(j+i-pos>=0&&j+i-pos<=7)chess[j][j+i-pos]--;
if(pos+i-j>=0&&pos+i-j<=7)chess[j][pos+i-j]--;
}
}
}
return;
}
int main(){
memset(chess,0,sizeof(chess));
string s;
getans(s,0);
int n;
while(scanf("%d",&n)!=EOF){
cout<<ans[n-1]<<endl;
}
}
- 直接判断当前位置是否可行,也可以简化标记过程
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int maxn=8;
bool col[8],lef[2*maxn-1],rig[2*maxn-1];//标记
string ans[93];//答案
int k=0;
void getans(string s,int pos){//已经排列坐标、查找行数
if(pos==8){
ans[k++].insert(0,s);//成功排列
return ;
}
for(int i=0;i<8;i++){//遍历pos这一行
if(!col[i]&&!lef[pos-i+maxn-1]&&!rig[pos+i]){//未被访问
col[i]=lef[pos-i+maxn-1]=rig[pos+i]=true;
char x=i+'1';
string next(s);
next.insert(next.end(),1,x);
getans(next,pos+1);//递归
col[i]=lef[pos-i+maxn-1]=rig[pos+i]=false;//清除本次标记
}
}
return;
}
int main(){
memset(col,false,sizeof(col));
memset(rig,false,sizeof(rig));
memset(lef,false,sizeof(lef));
string s;
getans(s,0);
int n;
while(scanf("%d",&n)!=EOF){
cout<<ans[n-1]<<endl;
}
}