• [HDU 2553]--N皇后问题(回溯)/N皇后问题的分析


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2553

    N皇后问题

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


    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   |   We have carefully selected several similar problems for you:  1016 1312 1241 1010 2614 
     
     
    N皇后问题可以说是一个经典的回溯问题,看看下面的动画对皇后问题的求解有了一个大致的想法;
     
    这里采用逐行放置的办法,那么就可以不用考虑皇后的横向攻击问题,只需要检查是否纵向和斜向攻击即可。
    斜向判断条件"cur - vis[cur] == j - vis[j] || cur + vis[cur] == j + vis[j]",原理用一下两个表来说明
    格子(x,y)的y-x标识了主对角线
     
     
    0 1 2 3 4 5 6 7
    -1 0 1 2 3 4 5 6
    -2 -1 0 1 2 3 4 5
    -3 -2 -1 0 1 2 3 4
    -4 -3 -2 -1 0 1 2 3
    -5 -4 -3 -2 -1 0 1 2
    -6 -5 -4 -3 -2 -1 0 1
    -7 -6 -5 -4 -3 -2 -1 0
     
     
     
     
     
     
     
     

     0  1  2  3  4 5 6 7
     1  2  3  4  5 6 7 8
     2  3  4  5  6 7 8 9
     3  4  5  6 7  8 9 10
     4  5  6  7  8  9 10 11
     5  6  7  8  9 10 11 12
     6  7  8  9 10 11 12 13
     7  8  9 10 11 12 13 14
    格子(x,y)的x+y标识了副对角线
     
     
     
     
     
     
     
     
    然后有一点特别坑的就是,这里虽然N<=10,但是是多组输入,刚开始一直超时,我习惯性的用cin输入,以为是这里的问题,
    改了还是超时,各种改各种超时,最后想到也许输入100组N<=10,有重复的N,如果把每个值存贮了就不用算第二次了,改了下
    总算过了。Orz~~~
     
    代码如下:
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int n, vis[11], cnt, ans[11];
     6 void Search(int cur){
     7     if (cur == n) cnt++;
     8     else for (int i = 0; i < n; i++){
     9         int flag = 1;
    10         vis[cur] = i;
    11         for (int j = 0; j < cur; j++){
    12             if (vis[cur] == vis[j] || cur - vis[cur] == j - vis[j] || cur + vis[cur] == j + vis[j]){
    13                 flag = 0;
    14                 break;
    15             }
    16         }
    17         if (flag) Search(cur + 1);
    18     }
    19 }
    20 int main(){
    21     memset(ans, -1, sizeof(ans));
    22     while (~scanf("%d", &n), n){
    23         //while (cin >> n, n){
    24         cnt = 0;
    25         if (ans[n] != -1){
    26             printf("%d
    ", ans[n]);
    27             continue;
    28         }
    29         Search(0);
    30         printf("%d
    ", cnt);
    31         ans[n] = cnt;
    32         //cout << cnt << endl;
    33     }
    34     return 0;
    35 }
    View Code

    如果要输出排列情况,代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int n, vis[11], cnt,T=1, ans[11];
     6 void Show(){
     7     for (int i = 0; i < n; i++){
     8         for (int j = 0; j < n; j++){
     9             if (j) cout << ' ';
    10             if (j == vis[i]) cout << char(3);
    11             else
    12                 cout << '.';
    13         }
    14         cout << endl;
    15     }
    16 }
    17 void Search(int cur){
    18     if (cur == n){
    19         cout << "Case:" << T++ << endl;
    20         Show();
    21         cnt++;
    22     }
    23     else for (int i = 0; i < n; i++){
    24         int flag = 1;
    25         vis[cur] = i;
    26         for (int j = 0; j < cur; j++){
    27             if (vis[cur] == vis[j] || cur - vis[cur] == j - vis[j] || cur + vis[cur] == j + vis[j]){
    28                 flag = 0;
    29                 break;
    30             }
    31         }
    32         if (flag) Search(cur + 1);
    33     }
    34 }
    35 int main(){
    36     memset(ans, -1, sizeof(ans));
    37     while (cout<<"请输入皇后数:",cin >> n, n){
    38         T = 1;
    39         cnt = 0;
    40         Search(0);
    41         cout << "总排列方式:"<<cnt << endl;
    42     }
    43     return 0;
    44 }
    View Code
  • 相关阅读:
    mysql最后一个内容orm
    mysql第五天:
    mysql第二天 数据的增删改查补充及外键
    MYsql 初识
    第二天openc的内容:图片的缩放、旋转、格式转换
    第二个内容第一天 opencv的基本内容:
    第五十七天 bom 的新知识
    第五十六天jQurey的内容新增:
    第五十五天jQery内容的进阶
    windows11 upgrade
  • 原文地址:https://www.cnblogs.com/zyxStar/p/4592219.html
Copyright © 2020-2023  润新知