Hdu2553 - N皇后问题 - 经典暴力回溯问题(非位运算做法)

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

思路

总体思路肯定是递归遍历解空间树,计算所有合法放置方式,复杂度是O(N!)(10的阶乘是3628800)

对于本题每次重复算会超时,所以我们要记录算过的答案,不然会TLE

根据题意我们知道一行只能放一个皇后,那么本题的重点是在每层判断皇后位置的合法性

1.对于每列,我们只需要用一个col数组标记,因为同理一列不可能存在两个皇后

2. 对于左上到右下的斜对角线,我们可以数字1 ~ 2 * n - 1标记每条对角线

6

7

8

9

10

11

5

6

7

8

9

10

4

5

6

7

8

9

3

4

5

6

7

8

2

3

4

5

6

7

1

2

3

4

5

6

对于第cur层的第i个位置如果lr[i - cur + n]为1,那么表示这条对角线已被标记了

3.对于右上到左下的斜对角线也同理

11

10

9

8

7

6

10

9

8

7

6

5

9

8

7

6

5

4

8

7

6

5

4

3

7

6

5

4

3

2

6

5

4

3

2

1

对于第cur层的第i个位置如果rl[i + cur]为1,那么表示这条对角线已被标记了

代码

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 12;
int lr[N << 1], col[N], rl[N << 1];
int n, ans;
int mp[N];
void dfs(int cur){
    if (cur == n + 1){
        ans ++;
        return ;
    }
    for (int i = 1; i <= n; ++ i){
        if (col[i] || lr[i - cur + n] || rl[cur + i])continue;
        col[i] = lr[i - cur + n] = rl[cur + i] = 1;
        dfs(cur + 1);
        col[i] = lr[i - cur + n] = rl[cur + i] = 0;
    }
}
int main()
{

    while (cin >> n && n){
        if (mp[n]){
            cout << mp[n] << endl;
            continue;
        }
        memset(lr, 0, sizeof(lr));
        memset(rl, 0, sizeof(rl));
        memset(col, 0, sizeof(col));
        ans = 0;
        dfs(1);
        mp[n] = ans;
        cout << ans << endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值