1. 程式人生 > >(藍橋杯)基礎練習 2n皇后問題

(藍橋杯)基礎練習 2n皇后問題

我們先學習下經典案例中的八皇后問題

接著學習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

認真學習了八皇后問題後這個題不是問題,只需要一個一個判斷,把條件稍微改下即可。

話不多說,上程式碼

#include<iostream>
#include<cstdio>

using namespace std;

int chess[8][8];//使用全域性變數,不用考慮二維陣列的傳入 
int count=0;
int n;
//黑皇后的判斷條件,多留心 
int notdanger(int row,int col)
{
    int flag1=0,flag2=0,flag3=0,flag4=0,flag5=0,flag6=0;
    //列
    for(int i=0;i<n;i++){
        if(chess[i][col]==2){
            flag1=1;
            break;
        }
    }
    //左上角
    for(int i=row,j=col;i>=0&&j>=0;i--,j--){
        if(chess[i][j]==2){
            flag2=1;
            break;
        }
    }
    //右上角
    for(int i=row,j=col;i>=0&&j<n;i--,j++){
        if(chess[i][j]==2){
            flag3=1;
            break;
        }
    }
    //右下角
    for(int i=row,j=col;i<n&&j<n;i++,j++){
        if(chess[i][j]==2){
            flag4=1;
            break;
        }
    }
    //左下角
    for(int i=row,j=col;i<n&&j>=0;i++,j--){
        if(chess[i][j]==2){
            flag5=1;
            break;
        }
    }
    //可不可以放 
    if(chess[row][col]==0){
        flag6=1;
    }
    if(flag1||flag2||flag3||flag4||flag5||flag6){
        return 0;
    }
    return 1;
}
//白皇后的判斷條件,這裡需要多留點心,一點兒寫錯都不行 
int bainotdanger(int row,int col)
{
    int flag1=0,flag2=0,flag3=0,flag4=0,flag5=0,flag6=0;
    //列
    for(int i=0;i<n;i++){
        if(chess[i][col]==3){
            flag1=1;
            break;
        }
    }
    //左上角
    for(int i=row,j=col;i>=0&&j>=0;i--,j--){
        if(chess[i][j]==3){
            flag2=1;
            break;
        }
    }
    //右上角
    for(int i=row,j=col;i>=0&&j<n;i--,j++){
        if(chess[i][j]==3){
            flag3=1;
            break;
        }
    }
    //右下角
    for(int i=row,j=col;i<n&&j<n;i++,j++){
        if(chess[i][j]==3){
            flag4=1;
            break;
        }
    }
    //左下角
    for(int i=row,j=col;i<n&&j>=0;i++,j--){
        if(chess[i][j]==3){
            flag5=1;
            break;
        }
    }
    //可不可以放
    if(chess[row][col]==0||chess[row][col]==2){
        flag6=1;
    }
    if(flag1||flag2||flag3||flag4||flag5||flag6){
        return 0;
    }
    return 1;
}

void baiQueen(int row)//判斷白皇后 
{
    if(row==n){
        count++;
    }else{
        for(int i=0;i<n;i++){
            if(bainotdanger(row,i)){
                chess[row][i]=3;
                baiQueen(row+1);
                chess[row][i]=1;
            }
        }
    }
}

void HeiQueen(int row)//判斷黑皇后 
{
    if(row==n){
        baiQueen(0);//黑皇后排好後,開始排白皇后 
    }else{
        for(int i=0;i<n;i++){
            if(notdanger(row,i)){
                chess[row][i]=2;
                HeiQueen(row+1);
                chess[row][i]=1;
            }
        }
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            scanf("%d",&chess[i][j]);
        }
    }
    HeiQueen(0);
    printf("%d\n",count);
    return 0;
}