您的位置:首页 > 其它

N皇后问题||HDU2553

2018-01-24 17:04 211 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2553

Problem Description

在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。


Input

共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。


Output

共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。


Sample Input

1
8
5
0


Sample Output

1
92
10


题解:这道题一开始并没有思路,是看了一个大佬的然后理解了自己敲出来的

思路的话,首先要搞清楚如果一行或者一列或者同在45°的一条线放了一个棋子,那么剩下的位置就不能再放置了。

如果我们按行遍历,那么这三个方向都有共同点,一个是列数相等,一个是列数-行数的值相等,一个是列数+行数值相等。

这样的话我们可以开始一个深度遍历,先设置一个标记变量使它能够表示这个位置是否可以放置棋子,然后一行一行的开始,然后一列挨着一列遍历,遇到一个符合条件的就进入下一行,最后如果遍历的行数和N相等,那么就代表有一种方法,然后退出这层遍历,并把刚刚标记值初始化(因为我们已经知道这个点可以放置,但是我们遍历下一点的时候他可能已经被标记过,然而我们目前这个方案并没有在那个点放置,所以需要初始化)。

具体看代码。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int vis[3][50],a[50];
int n,sum;
void dfs(int row)
{
int i;
if(row==n+1)//已经遍历了N行
{
sum++;
return;
}
for(i=1;i<=n;i++)
{
if(vis[0][row-i+n]==0&&vis[1][i]==0&&vis[2][row+i]==0)//表示目前这三个方向没有放置棋子
{
vis[0][row-i+n]=vis[1][i]=vis[2][row+i]=1;//标记,假设已经放置
dfs(row+1);//遍历下一行
vis[0][row-i+n]=vis[1][i]=vis[2][row+i]=0;//返回当前行,并把标记取消
}
}
}
int main()
{
for(n=1;n<=10;n++)//先打表,不然会超时
{
sum=0;
memset(vis,0,sizeof(vis));
dfs(1);
a
=sum;
}
int x;
while(scanf("%d",&x),x)
{
printf("%d\n",a[x]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: