您的位置:首页 > 其它

n后问题

2016-12-25 16:53 106 查看
n后问题

    在n*n的棋盘上放置彼此不受攻击的n个皇后,按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于在n*n格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。

样例输入

7

8

样例输出

40

92

解法1(暴力):

n个皇后放置于n*n的矩阵中,有n*n种方式 
利用 n 进制,进行每个皇后放置
每一行一定出现一个皇后,用x[j]数组存放 第 j 行的 皇后放置的列数
所以此时 i 换成n位 n 进制之后赋值给 x 数组
对每种情况进行列与对角线的判断。

#include <stdio.h>
#include <string.h>
#include <math.h>

int n;
int x[100];

int main()
{
scanf("%d",&n);
int count=0;
for(int i=0;i<pow(n,n);i++)
{
int j=i;
int flag=1;
for(int a=0;a<n;a++)
{
x[a]=j%n;
j/=n;
}
for(int z=0;z<n;z++)
{
for(int k=0;k<z;k++)
{
if(x[z]==x[k] || (fabs(k-z)==fabs(x[k]-x[z])))
flag=0;
}
}
if(flag==1)
count++;
}
printf("%d\n",count);
return 0;
}

解法2(回溯):

要求同一行、同一列、对角线上没有两个皇后存在
所以每一行一定出现一个皇后,用x[i]数组存放 第 i 行的 皇后放置的列数
所以,此时可以对 x 数组的每一位进行回溯,当 t==n 时代表 n 个皇后已经放置完毕 
因为在放置皇后的过程中已经进行判断,所以此时已经不可能出项不符合规定的情况。
方案数直接进行自加即可。

因为x[i]中存放皇后出现的列数,所以判断是否满足情况的时候,不需要判断一行是否有两个皇后,
每放置一个皇后,进行判断此处是否能放置,
此时对角线的判断已经变成:   fabs(k-i)==fabs(x[k]-x[i])

#include <stdio.h>
#include <string.h>
#include <math.h>
int n;
int x[100];
int count=0;

bool ok(int k)
{
for(int i=0;i<k;i++)
{
if(x[i]==x[k] || (fabs(k-i)==fabs(x[k]-x[i])))
return false;
}
return true;
}

void dfs(int t)
{
if(t==n)
{
count++;
return;
}
for(int i=0;i<n;i++)
{
x[t]=i;
if(ok(t))
dfs(t+1);
}
}
int main()
{
scanf("%d",&n);
dfs(0);
printf("%d\n",count);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息