还没有看大佬的代码,分享我的最朴素的思想。。。
遍历一个8*8的图,一行一行进行遍历。
每遍历一个点,就把该点的行,列和左斜线,右斜线都进行标记。
然后继续访问,如果到了最后一行,那么成功。如果还没到最后一行,就已经都标记完了,则进行回溯。
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=8;
int g[maxn][maxn];
vector<int> vec;
int res=0,n;
void dfs(int now){//now表示当前行
if(now==maxn){
vec.push_back(res);
return ;
}
bool flag=false;
for(int i=0;i<maxn;i++){ //第i列
if(g[now][i]==0){
res=res*10+i+1; //用来存储结果
for(int j=i;j<maxn;j++){//把这行后边的列都标记了
if(g[now][j]==0) g[now][j]=now+1;
}
int l=i-1,r=i+1;
for(int j=now+1;j<maxn;j++){//把这列下边的行都标记了
if(g[j][i]==0)g[j][i]=now+1;
if(l>=0&&g[j][l]==0) g[j][l]=now+1;//把左斜线的标记了
if(r<maxn&&g[j][r]==0) g[j][r]=now+1;//把右斜线的标记了
l--;r++;
}
dfs(now+1);//递归进入下一层
for(int j=i;j<maxn;j++){//回溯(把上一轮标记的取消标记)
if(g[now][j]==now+1) g[now][j]=0;
}
l=i-1;r=i+1;
for(int j=now+1;j<maxn;j++){//回溯(把上一轮标记的取消标记)
if(g[j][i]==now+1) g[j][i]=0;
if(l>=0&&g[j][l]==now+1) g[j][l]=0;
if(r<maxn&&g[j][r]==now+1) g[j][r]=0;
l--;r++;
}
res-=(i+1); res/=10;
}
}
}
int main(){
memset(g,0,sizeof(g));
dfs(0);
sort(vec.begin(),vec.end());
while(cin>>n){
cout<<vec[n-1]<<endl;
}
return 0;
}


京公网安备 11010502036488号