1. 程式人生 > >八皇后問題(C語言版本)

八皇后問題(C語言版本)

八皇后問題是一個古老而著名的問題,是回溯演算法的典型例題。該問題是十九世紀著名的數學家高斯1850年提出:在8X8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線(對角線)上,問有多少種擺法。

解決方法1

下面的C程式碼可以解決N皇后問題,8皇后問題的解是92。

#include <stdio.h>
#include <stdlib.h>
 
#define max 8
 
int queen[max], sum=0; /* max為棋盤最大座標 */
 
void show() /* 輸出所有皇后的座標 */
{
    int i;
    for(i = 0; i < max; i++)
    {
         printf("(%d,%d) ", i, queen[i]);
    }
    printf("\n");
    sum++;
}
 
int check(int n) /* 檢查當前列能否放置皇后 */
{
    int i;
    for(i = 0; i < n; i++) /* 檢查橫排和對角線上是否可以放置皇后 */
    {
        if(queen[i] == queen[n] || abs(queen[i] - queen[n]) == (n - i))
        {
            return 1;
        }
    }
    return 0;
}
 
void put(int n) /* 回溯嘗試皇后位置,n為橫座標 */
{
    int i;
    for(i = 0; i < max; i++)
    {       
        queen[n] = i; /* 將皇后擺到當前迴圈到的位置 */
        if(!check(n))
        {           
            if(n == max - 1)
            {
                show(); /* 如果全部擺好,則輸出所有皇后的座標 */
            }         
            else
            {
                put(n + 1); /* 否則繼續擺放下一個皇后 */
            }
        }
    }
}
 
int main()
{
    put(0); /* 從橫座標為0開始依次嘗試 */
    printf("%d", sum);
    return 0;
}
程式執行部分結果截圖:


解決方法2

                                            由於8個皇后的任意兩個不能處在同一行,那麼肯定是每一個皇后佔據一行。於是我們可以定義一個數組ColumnIndex[8],陣列中第i個數字表示位於第i行的皇后的列號。先把陣列ColumnIndex的8個數字分別用0~7初始化,接下來就是對陣列ColumnIndex做全排列。因為我們是用不同的數字初始化陣列,所以任意兩個皇后肯定不同列。我們只需要判斷每一個排列對應的8個皇后是不是在同一對角線上,也就是對於陣列的兩個下標i和j,是不是 i-j==ColumnIndex[i]-ColumnIndex[j]或者 j-i==ColumnIndex[i]-ColumnIndex[j]。
示例程式碼如下:
int queenNumber=0;
//判斷是否是合法的序列
bool JudgeValid(int* array,int length){
	for(int i=0;i<length-1;i++)
		for(int j=i+1;j<length;j++){
			if(i-j==array[i]-array[j] || j-i==array[i]-array[j])
				return false;
		}
		return true;
}

//獲得皇后問題的全排列
void QueuePermutation(int* array,int beginIndex,int length){
	if(beginIndex==length){
		if(JudgeValid(array,length))
			++queenNumber;
	}else{
		for(int curSub=beginIndex;curSub!=length;curSub++){
			int temp=array[beginIndex];
			array[beginIndex]=array[curSub];
			array[curSub]=temp;
			QueuePermutation(array,beginIndex+1,length);
			temp=array[beginIndex];
			array[beginIndex]=array[curSub];
			array[curSub]=temp;
		}
	}
}

//可以解決N皇后問題
void QueueProgram(int length){
	int *array=new int[length];
	for(int i=0;i<length;i++)
		array[i]=i;//初始化陣列
	QueuePermutation(array,0,length);
} 

結果輸出為:92。對於合法排列,可以輸出皇后放置的詳細位置。