回溯法--N皇后問題

一般是八皇后,首先是算法思想如下:

void generate(int n){
	int col;
	for(col=0;col<=7;col++){
		if(不衝突){
			放置,並且宣佈佔領
			if(n<7){
				generate(n+1);
			}else{
				printf();//打印 
			}
			回溯,取消佔領. 
		}
	}
}

主函數如下:首先從0開始,也就是第一行開始逐級向下

int main(){
	generate(0);
	cout<<"擺放方式有:"<<counts<<"種!"<<endl;
	return 0;
}

遞歸函數如下:

void generate(int n){
	int col;
	for(col=0;col<8;col++){//棋盤一共八行八列,此處主要是每一層用於判斷每一列是否符合條件 
		if(flag[col]&&d1[n-col+7]&&d2[n+col]){//括號內是算法的精髓,理解了此處,N皇后問題就不難,主要是根據八皇后棋盤的性質,
		                                      //如兩個座標,如果行數-列數對應的值相同,那麼就必然在同一對角線,此時跳出if從而判斷下一位置 
			Queens[n]=col;//符合上述條件之後,就把皇后放置在col列,並且把相對於的列,上對角線,下對角線的標記改爲false,方便之後的判斷 
			flag[col]=false;
			d1[n-col+7]=false;
			d2[n+col]=false;
			if(n<7){
				generate(n+1);
			}else{
				print();
			}
			flag[col]=true;//回溯考慮上一層的情況,並且把這一層改過來的false改爲true 
			d1[n-col+7]=true;
			d2[n+col]=true;
		}
	}
}

輸出函數如下:

void print(){
	int col,i,j;
	counts++;
	cout<<"No."<<counts<<endl;
	int table[8][8]={};//定義一個8*8的棋盤數組,起始每個元素都是0 
	for(col=0;col<8;col++){
		table[col][Queens[col]]=1;//Queens[col]保存的是皇后所在的列數 
	}
	for(i=0;i<8;i++){
		for(j=0;j<8;j++){
			cout<<table[i][j]<<" ";
		}
		cout<<endl;
	}
}

頭部聲明以及全局變量如下:

#include <iostream>
#include <algorithm>
using namespace std;
int Queens[8]={};//表示第n個皇后佔位置的列號 
int counts=0;//counts記錄能擺放的棋盤方式個數 
bool flag[8]={1,1,1,1,1,1,1,1};//標誌數組,表示第col列是否可佔,1表示可佔 
bool d1[15]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};//表示上對角線是否可佔 爲什麼是15呢?
//因爲在d1[n-col+7]中爲了避免出現負數,所以要+7,而原來可能是7的現在變成了14 
bool d2[15]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};//表示下對角線是否可佔  

 

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