zoukankan      html  css  js  c++  java
  • HDU2553 N皇后问题——DFS

    N皇后问题

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


    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

    题意:中文题。。。。。

    思路:非常经典的搜索问题,用DFS来写。在棋盘中的棋,它的上下左右,以及左上,右上,左下,右下都不能有棋。因为是N*N的棋盘要放N个棋,可以知道一定是每一行放一个棋,所以我们可以按行进行搜索,逐一确定每一行的棋放在这一行的哪一个位置。

    这样有什么好处呢?这样就可以不用担心会发生两个棋子在同一行的情况了,而且也不用管这一行之前的行的情况了,因为能搜索到这一行,之前的每一个都应该是合法的。

    然后如何标记那些位置不能走呢?首先,行不用标记,原因上面说了,列也好办,开一个标记列的数组就行了。

    那左下和右下怎么办呢?仔细观察可以发现当前点到左下角45度这一条线路的所有点行数+列数的值都是相等的,而到右下角45度这一条线路行数-列数的值都是相等的,所以我们可以考虑用行和列的和来标记左下,行和列的差来标记右下,这样就是普通的DFS模板了。

    这题还有一个坑点,就是n是循环输入的,一组测试数据要DFS很多次,如果直接交的话会超时。因为n<=10,所以可以提前求出n==1到10的答案,存下,然后再输入n的时候直接用就行了。

    代码:

     1 #include<iostream> 
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<string>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<stack>
     8 #include<queue>
     9 #define eps 1e-7
    10 #define ll long long
    11 #define inf 0x3f3f3f3f
    12 #define pi 3.141592653589793238462643383279
    13 using namespace std;
    14 int ldown[20],rdown[30],vcolu[30]; //ldown标记左下,rdown标记右下,vcolu标记列 
    15 int n,ans[20];
    16 
    17 void DFS(int all,int cnt)
    18 {
    19     if(cnt == all+1) //如果最后一行也已经放了棋子,递归到了n+1行,答案++; 
    20     {
    21         ans[all]++;
    22         return;
    23     }
    24     
    25     for(int i=1; i<=all; ++i) //枚举这一行的每一列 
    26     {
    27         if(!vcolu[i] && !ldown[cnt+i] && !rdown[10+cnt-i]) //如果列,左下,右下都未标记不能走,则这一点可以走 
    28         {
    29             vcolu[i] = 1; //列标记为不能走 
    30             ldown[cnt+i] = 1; //左下标记为不能走 
    31             rdown[10+cnt-i] = 1; //右下。。。因为cnt-i可能为负,所以加上10避免 
    32             DFS(all,cnt+1); //递归搜索下一行 
    33             vcolu[i] = 0; //回溯 
    34             ldown[cnt+i] = 0;
    35             rdown[10+cnt-i] = 0;
    36         }
    37     }
    38     return;
    39 }
    40 
    41 int main()
    42 {
    43     memset(vcolu,0,sizeof(vcolu));
    44     memset(ldown,0,sizeof(ldown));
    45     memset(rdown,0,sizeof(rdown));
    46     memset(ans,0,sizeof(ans));
    47     for(int i=1; i<=10; ++i) //预处理枚举n为1到10的答案 
    48     {
    49         DFS(i,1);
    50     }
    51     while(cin>>n)
    52     {
    53         if(n==0) break;
    54         cout<<ans[n]<<endl;
    55     }
    56     return 0;
    57 }
  • 相关阅读:
    python json 和 pickle的补充 hashlib configparser logging
    go 流程语句 if goto for swich
    go array slice map make new操作
    go 基础
    块级元素 行内元素 空元素
    咽炎就医用药(慢性肥厚性咽炎)
    春季感冒是风寒还是风热(转的文章)
    秋季感冒 咳嗽 怎么选药
    解决IE浏览器“无法显示此网页”的问题
    常用的 css 样式 记录
  • 原文地址:https://www.cnblogs.com/tuyang1129/p/9311913.html
Copyright © 2011-2022 走看看