一篇文章帶你快速搞懂 2n皇后問題

題目描述:

給定一個n*n的棋盤,棋盤中有一些位置不能放皇后。現在要向棋盤中放入n個黑皇后和n個白皇后,使任意的兩個黑皇后都不在同一行、同一列或同一條斜線(包括正負斜線)上,任意的兩個白皇后都不在同一行、同一列或同一條斜線(包括正負斜線)上。問共有多少种放法?n<=8。

輸入:

第一行輸入一個整數n,表示棋盤的大小。
接下來n行,每行n個0或1的整數。如果一個整數爲1,表示對應的位置可以放皇后,如果一個整數爲0,表示對應的位置不可以放皇后。

輸出:

輸出所有可以按照要求擺放n*n的棋盤,若沒有則不輸出。
注意:數字2表示可以放置黑皇后,數字3表示可以放置白皇后。
最後輸出一個整數,表示總共有多少种放法。

思路:

先擺放完黑皇后,再擺放白皇后。
從第1行到第n行依次擺放皇后。
擺放皇后檢查哪列可以擺放。
注意:只有當mp[][]爲1時纔可以擺放皇后。因爲擺放此皇后之前可能已經擺放了其他皇后。例如,擺放白皇后時,某位已擺放了黑皇后,數字變成了2!

注:其他細節問題均已註釋在代碼中!

代碼如下:

#include<cstdio>
#include<cmath>
int n,ans;
int mp[9][9];
//mp[][]爲0則不可放置皇后,爲1則可放置皇后,爲2則可以放置黑皇后,爲3則可以放置白皇后
bool judge(int x,int y,int k){
	//判斷(x,y)位置的k皇后是否與前x-1行的k皇后是否衝突
	if(x==1)
		return true;
	for(int i=1;i<x;++i){
		if(mp[i][y]==k)
			return false;
		for(int j=1;j<=n;++j){
			if(abs(x-i)==abs(y-j)&&mp[i][j]==k){
				return false;
			}
		}
	}
	return true;
} 
void dfs(int x,int k){
	if(x==n+1&&k==3){		//黑白皇后放置完畢
		++ans;
		for(int i=1;i<=n;++i){
			for(int j=1;j<=n;++j){
				printf("%-2d",mp[i][j]);
			}
			printf("\n");
		}
		printf("\n");
		return;
	} 
	if(x==n+1&&k==2){		//黑皇后放置完畢,開始放置白皇后
		dfs(1,3);
		return;
	}
	for(int i=1;i<=n;++i){	//對x行k皇后檢查哪列可以放置 
		if(mp[x][i]==1&&judge(x,i,k)){
			mp[x][i]=k;
			dfs(x+1,k);
			mp[x][i]=1;    //因爲是求所有解,所以需要回溯!
		}
	}
}
int main(){
	scanf("%d",&n);			//輸入棋盤規格 
	for(int i=1;i<=n;++i){	//輸入棋盤 
		for(int j=1;j<=n;++j){
			scanf("%d",&mp[i][j]);
		}
	}
	printf("\n");
	dfs(1,2);
	printf("%d",ans);
	return 0;
} 

運行結果:

大一小白編寫代碼水平有限,如果對您有幫助,請點贊支持,感謝!
大一小白編寫代碼水平有限,如果對您有幫助,請點贊支持,感謝!
大一小白編寫代碼水平有限,如果對您有幫助,請點贊支持,感謝!

最後,如果你也是一名小白,歡迎添加博主微信:xinglibao465 互相交流進步!感謝!
最後,如果你也是一名小白,歡迎添加博主微信:xinglibao465 互相交流進步!感謝!
最後,如果你也是一名小白,歡迎添加博主微信:xinglibao465 互相交流進步!感謝! 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章