1. 程式人生 > >資料結構程式設計回顧(三)八皇后問題(遞迴)

資料結構程式設計回顧(三)八皇后問題(遞迴)

設計要求:八皇后問題是在8×8 的國際象棋棋盤上安放8
個皇后,要求沒有一個皇后能夠“吃掉”任何其他一個皇后,
即沒有兩個或多個皇后佔據棋盤上的同一行、同一列或者同
一條對角線。
說明:在實際問題中,有相當一類問題需要找出它的解集合,
或者要找出某些約束條件下的最優解。求解時通常使用一種
稱為回溯的方法來解決,所謂回溯就是走回頭路,該方法是
在一定的約束條件下試探地搜尋前進,若前進中受阻,則回
頭另擇通路繼續搜尋。

 

由於作者比較懶,當年就用了遞迴實現而已,沒有用棧的非遞迴實現。

由定義可知,每行必定有且僅有一個皇后,使用一維陣列儲存即可,每個元素儲存這一行元素的位置。

根據已知條件(同行、同列或同一一條線)不能放置兩個皇后(後來知道皇后是可以橫著走斜著走豎著走的,如果滿足這些條件會被吃掉),判斷第n行第i列是否能放置皇后:

int puts(int n,int i){
int j;

for(j=0;j<n-1;j++){
	if(queens[j]==i||((n-j)==(queens[n]-queens[j]))||((n-j)==(queens[j]-queens[n])))
	return 0;

}
return 1;}

遞迴體:

如果n==總行數,即0~n-1已經放置完成,則解法+1,並輸出改解法。

否則,對這行的每個位置進行判斷是否能放置,如果能,則進行下一行的放置,否則,退回上一層,繼續測試上一層的下一個位置。

int queen(int n){
	if(n==num)
	{   c++;
		print();
		return 0;
	}
int i;
for(i=0;i<num;i++){
	queens[n]=i;
	if(puts(n,i)==1){
		queen(n+1);
	}

}
}

 

完整程式碼:

#include <iostream>
#include <string.h>

//八皇后問題
int queens[100];

int num;
int c;

using namespace std;
void print(){
	int i,j;
	cout<<endl<<"---------------"<<endl;
	cout<<"第"<<c<<"種解法"<<endl;
	for(i=0;i<num;i++){
		for(j=0;j<num;j++){

			if(queens[i]==j)
			cout<<'T';
			else
			cout<<'O';

			cout<<' ';
		}

		cout<<endl;
	}

}
int puts(int n,int i){
int j;

for(j=0;j<n-1;j++){
	if(queens[j]==i||((n-j)==(queens[n]-queens[j]))||((n-j)==(queens[j]-queens[n])))
	return 0;

}
return 1;}
int queen(int n){
	if(n==num)
	{   c++;
		print();
		return 0;
	}
int i;
for(i=0;i<num;i++){
	queens[n]=i;
	if(puts(n,i)==1){
		queen(n+1);
	}

}
}

int main()
{
	cout<<"N queens problem\n"<<"pls input n:";

	cin>>num;
    queen(0);

    cout<<"共有"<<c<<"種解法.";
    return 0;
}