1. 程式人生 > >n皇後問題與2n皇後問題

n皇後問題與2n皇後問題

輸出格式 esp 嘗試 names namespace clu pre stdlib.h 如果

n皇後問題 問題描述:   如何能夠在 n×n 的棋盤上放置n個皇後,使得任何一個皇後都無法直接吃掉其他的皇後 (任兩個皇後都不能處於同一條橫行、縱行或斜線上) 結題思路:   可采用深度優先算法,將棋盤看成一個n*n的地圖,每層有n個頂點,共有n層。然後套用dfs,每一層要判斷與前面的皇後會不會沖突,如果不會,則可以放置皇後(可以走這個頂點),直到最後一層,將解決方案數量加一就行了。 註:用一維數組 queen[10] 即可代表女皇的橫豎坐標,下標為第幾行,結果則為第幾列。   當 abs(queen[i] - queen[n]) == abs(n - i) 時說明在一個斜線上(y2-y1==x2-x1 說明兩點成45°角)
#include <stdio.h>
#include 
<stdlib.h> #include <iostream> using namespace std; int queen[10], sum=0; int Max; //此函數用於判斷皇後當前皇後是否可以放在此位置 int PLACE(int n) /* 檢查當前列能否放置皇後 */ {//abs(queen[i] - queen[n]) == abs(n - i)用於約束元素不能再同一行且不能再同一條斜線上 int i; for(i = 1; i < n; i++) /* 檢查橫排和對角線上是否可以放置皇後 */ { if(queen[i] == queen[n] || abs(queen[i] - queen[n]) == abs(n - i)) {
return 0; } } return 1; } //核心函數,回溯法的思想 void NQUEENS(int n) /* 回溯嘗試皇後位置,n為橫坐標 */ { int i; for(i = 0; i < Max; i++) { queen[n] = i; if(PLACE(n)) { if(n == Max) { sum++; } else { NQUEENS(n
+ 1); } } } } int main() { cin>>Max; NQUEENS(1); /* 從橫坐標為0開始依次嘗試 */ printf("總共的解法有%d種\n", sum); return 0; }

2n皇後: 問題描述   給定一個n*n的棋盤,棋盤中有一些位置不能放皇後。現在要向棋盤中放入n個黑皇後和n個白皇後,使任意的兩個黑皇後都不在同一行、同一列或同一條對角線上,任意的兩個白皇後都不在同一行、同一列或同一條對角線上。問總共有多少種放法?n小於等於8。 輸入格式   輸入的第一行為一個整數n,表示棋盤的大小。
  接下來n行,每行n個0或1的整數,如果一個整數為1,表示對應的位置可以放皇後,如果一個整數為0,表示對應的位置不可以放皇後。 輸出格式   輸出一個整數,表示總共有多少種放法。 樣例輸入 4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1 樣例輸出 2 樣例輸入 4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1 樣例輸出 0 知道n皇後怎麽解後2n皇後就容易理解了。只要在白皇後擺放好後再用同樣的方式擺放黑皇後即可,不過也要註意白皇後不能和黑皇後擺在同一個位置(i!=wqueen[n])
以及map上值為0不能擺放皇後,加上這兩個兩個條件即可。
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

int bqueen[10], wqueen[10], sum=0;     // Max為棋盤最大坐標 
int Max;
int map[10][10];                    //map用於判斷白皇後是否已經放置(2) 或 該位置可以放置(1) 或 不可放置(0)


int w_place(int n) /* 檢查當前列能否放置白皇後 */
{
    int i;                    //第i個皇後 
    for(i = 0; i < n; i++)     //檢查橫排和對角線上是否可以放置皇後
    {
        if(wqueen[i]==wqueen[n] || abs(wqueen[i]-wqueen[n])==abs(n-i))
        {
            return 0;
        }
    }
    return 1;
}

int b_place(int n)
{
    int i;                    //第i個皇後 
    for(i = 0; i < n; i++)     //檢查橫排和對角線上是否可以放置皇後
    {
        if(bqueen[i]==bqueen[n] || abs(bqueen[i]-bqueen[n])==abs(n-i))
        {
            return 0;
        }
    }
    return 1;
}


void b_queen(int n)
{
    int i;
    for(i=0; i<Max; i++)
    {
        if(map[n][i])
        {
            bqueen[n] = i;
            if(b_place(n) && i!=wqueen[n])    //判斷可以擺在該坐標 
            {
                if(n==Max-1)    //判斷是否是最後一個皇後(最後一行) 
                {
                    sum++; 
                } 
                else
                {
                    b_queen(n+1);
                }
            }
        }
    }
}


void w_queen(int n) /* 回溯嘗試皇後位置,n為橫坐標 */
{
    int i;
    for(i=0; i<Max; i++)
    {
        if(map[n][i])
        {
            wqueen[n] = i;
            if(w_place(n))
            {
                if(n==Max-1)
                {
                    b_queen(0);
                }
                else
                {
                    w_queen(n+1);
                }
            }
        }
    }
}

int main()
{
    cin>>Max;
    for(int i=0; i<Max; i++)
        for(int j=0; j<Max; j++)
            scanf("%d", &map[i][j]);        
    w_queen(0);
    printf("%d\n", sum);

    return 0;
}

n皇後問題與2n皇後問題