题目链接:https://www.luogu.org/problemnew/show/P1219
思路:回溯,标记。开四个数组a代表行,b代表列,book代表右上到左下的对角线,vis代表左上到右下的对角线。我们发现:
对于一条从右上到左下的对角线,其上的棋子坐标应满足x+y为一定值;
对于一条从左上到右下的对角线,其上的棋子坐标应满足x-y为一定值,为了避免负数的产生,代码中用x-y+n来储存数字
只要满足条件就打上标记往下搜索,不满足就取消标记回溯。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int a[2000], b[2000], vis[2000], book[2000], n, t;
void dfs(int j)
{
if(j - 1 == n)
{
if(t < 3)
{
for(int i = 1; i <= n; i++)
cout << a[i] << " ";
cout << endl;
}
t++;
return;
}
for(int i = 1; i <= n; i++)
{
if(!b[i] && !book[i+j] && !vis[i-j+n])
{
b[i] = 1; book[i+j] = 1;
vis[i-j+n] = 1;
a[j] = i;
dfs(j+1);
b[i] = 0; book[i+j] = 0;
vis[i-j+n] = 0;
}
}
}
int main()
{
while(~scanf("%d",&n))
{
memset(vis,0,sizeof(vis));
memset(book,0,sizeof(book));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
t = 0;
dfs(1); printf("%d\n",t);
}
}