N皇后问题||HDU2553

题目链接: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[n]=sum;
    }
    int x;
    while(scanf("%d",&x),x)
    {
        printf("%d\n",a[x]);
    }
return 0;
} 

猜你喜欢

转载自blog.csdn.net/csdn_muxin/article/details/79153064