题目
分析
和模版题的不同
输出时,要求输出按照字典序排列的前三个解,以及解的总数
看到字典序
我想到,用string s[N]存下所有的解,然后对s进行sort排序,就可以把所有的解进行字典序排序了
没错
但是不排序也没事,因为遍历填写列的时候,就是从小到大遍历的,因此答案的结果也就自然会按照字典序排列
易错点
没必要的存储
可以只存下前三个解,当idx>3时,可以不用存了
没必要的操作
sort排序
因此也可以用int ans[3][N];
关于对照中的易错点
如果映射成字符的阿拉伯数字,超过9之后就会出现错误(这一点在很多场合中都容易忘记出错)
所以我映射成了A B C....
然后建立一个从字母到数字的表用于输出
关于下标的问题
up中的下标不能直接写[i-u],因为会出现负数,为了防止出现负数,+n进行平移,[i-u+n]
这种思路在很多中常见(有点像取模防止负数的思路)
#include <bits/stdc++.h>
using namespace std;
const int N=15;
const int M=N*2;
const int SIZE=1e6+7;
int n;
int res[N];//当前结果
int col[N],up[M],down[M];
string ans[SIZE];
int idx;
//下标0要空出来,因为答案存的是从1开始填写的
int contrast[14]={0,1,2,3,4,5,6,7,8,9,10,11,12,13};
void dfs(int u)
{
//当前要填写的是第u行
if(u==n+1){
//表示第1行到第n行都填好了,把答案存到ans字符串数组中
for(int i=1;i<=n;i++){
ans[idx]+=res[i]+'A';
//易错点:如果存成数字,10、11...就无法用一个字符村
//把数字存成字母,因为n最大是13<26,所以足够的
//注意,因为要用字典序,所以要保证映射前后,字符间的相对字典序是不变的
}
idx++;
return ;
}
//填写第u行
for(int i=1;i<=n;i++){
if(!col[i]&&!up[i-u+n]&&!down[i+u]){
res[u]=i;
col[i]=up[i-u+n]=down[i+u]=true;
dfs(u+1);
col[i]=up[i-u+n]=down[i+u]=false;
}
}
}
int main()
{
scanf("%d",&n);
dfs(1);
sort(ans,ans+idx);//没有排序也是按照字典序输出,因为我们遍历列的时候是从小到大遍历的
for(int i=0;i<3;i++){
for(int j=0;j<ans[i].size();j++) printf("%d ",contrast[ans[i][j]-'A']);
printf("\n");
}
printf("%d\n",idx);
return 0;
}