你的任务是,对于给定的N,求出有多少种合法的放置方法。
1 8 5 0
Sample Output
1 92 10思路:明显是用回溯法,这里比较难的是对角线,列的状态表示,列的状态用vis[0][j]表示即可,对角线的表示比较麻烦,所以我用了刘汝佳的表示方法,vis[1][i+j]表示主对角线的状态,vis[2][j-i+n]来表示副对角线的状态(因为j-i有可能是负的,所以加n)
下面是ac代码(有可能因为测试数据过大,如果显示超时,直接打表)
#include<cstdio>
#include<string.h>
int vis[3][100],n,ans;
void dfs(int x)
{
if(x>=n)
{
ans++;
return;
}
for(int i=0;i<n;i++)
{
if(!vis[0][i]&&!vis[1][i+x]&&!vis[2][i-x+n])
{
vis[0][i]=vis[1][i+x]=vis[2][i-x+n]=1;
dfs(x+1);
vis[0][i]=vis[1][i+x]=vis[2][i-x+n]=0;
}
}
}
int main()
{
while(~scanf("%d",&n))
{
memset(vis,0,sizeof(vis));
ans=0;
dfs(0);
printf("%d\n",ans);
}
}
打表代码:
#include<cstdio>
#include<string.h>
#define maxn 20
int vis[3][maxn],n,ans;
int dfs(int x)
{
if(x==2||x==3)
return 0;
else if(x==1)
return 1;
else if(x==4)
return 2;
else if(x==5)
return 10;
else if(x==6)
return 4;
else if(x==7)
return 40;
else if(x==8)
return 92;
else if(x==9)
return 352;
else if(x==10)
return 724;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==0)
return 0;
memset(vis,0,sizeof(vis));
ans=0;
ans=dfs(n);
printf("%d\n",ans);
}
return 0;
}