HDU - 2553 N皇后問題(DFS)

sunlanchang發表於2019-02-01

Description

在N*N的方格棋盤放置了N個皇后,使得它們不相互攻擊(即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。
你的任務是,對於給定的N,求出有多少種合法的放置方法。

Input

共有若干行,每行一個正整數N≤10,表示棋盤和皇后的數量;如果N=0,表示結束。

Output

共有若干行,每行一個正整數,表示對應輸入行的皇后的不同放置數量。

Sample Input

1
8
5
0

Sample Output

1
92
10

Solution

判斷對角線時候:

  • 在 (↖)方向上列-行的差是相等的,假如我們用陣列儲存負數肯定是不行的, 所以我們要加上 n,讓他變為非負。
  • (↗)方向上的資料的行和列的特點是 在 (↗)方向上列+行的和是相等的。

參考https://www.cnblogs.com/chenchengxun/p/3759278.html

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
int vis[3][50], P[15]; //三個方向 ↖↑↗在此三個方向都不能有皇后
int n, sum;

void DFS(int row)
{
    int i;
    if (row == n + 1) //遞迴結束
    {
        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++) //先打表不然會超時的
    {
        memset(vis, 0, sizeof(vis));
        sum = 0;
        // 提前計算出1*1、2*2、3*3...等n皇后問題
        DFS(1);
        P[n] = sum;
    }
    while (scanf("%d", &n), n)
    {
        printf("%d\n", P[n]);
    }
    return 0;
}

相關文章