现在的位置: 首页 > 综合 > 正文

hdu 2553 N皇后问题

2012年12月08日 ⁄ 综合 ⁄ 共 1538字 ⁄ 字号 评论关闭

N皇后问题

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5300 Accepted Submission(s): 2409

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

Author
cgf

Source

Recommend
lcy

关键是解决对角线问题

以8*8为例
                                   
 列数-行数(i-j) 
                                                                                                                
    

                                       

                           主对角线 

                                        列数+行数(i+j)

                                                                                                                                                             
              

                              副对角线                                                  

会发现对角线上上的数字都是相等的。所以每条对角线用一个标记变量记录状态就行了。比如一个n*n的网格用大小为2*n-1个的数组标记。如果当前格的坐标为i行j列的话。映射到主对角线就为j-i.但数组下标不能是负数。所以再加一个n-1就转化非负数了。如左图对应从左下到右上就为。0,1,2,3,4,5,6,7,8,9,10,11,12,13,14。副对角线就直接映射就行了。.这样就使判断是否同对角线简单多了。其次这题要记录答案。已计算过的数据直接输出答案不然会超时。

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

int l[29],r[29],row[15],ans[15],sum,n;
//l标记主对角线。r标记副对角线。row标记列是否被访问
void dfs(int p)//p代表当前需放皇后行数
{
    int i;
    if(p==n)//如果每行都放有皇后(从0开始放到n-1行)
    {
        sum++;//方法数加1
        return ;
    }
    for(i=0;i<n;i++)//对列进行搜索
    {
        if(!row[i]&&!l[i-p+n-1]&&!r[i+p])//判断该列。所在主对角线。副对角线是否已有皇后
        {
            row[i]=1;
            l[i-p+n-1]=1;//见上解释
            r[i+p]=1;
            dfs(p+1);//继续深搜
            row[i]=0;//回溯
            l[i-p+n-1]=0;
            r[i+p]=0;
        }
    }
}
int main()
{
    memset(ans,-1,sizeof ans);
    while(scanf("%d",&n),n)
    {
        if(ans[n]!=-1)
        {
            printf("%d\n",ans[n]);
            continue;
        }
        memset(l,0,sizeof l);
        memset(r,0,sizeof r);
        memset(row,0,sizeof row);
        sum=0;
        dfs(0);//从0行开始搜索
        ans[n]=sum;
        printf("%d\n",sum);
    }
    return 0;
}

抱歉!评论已关闭.