1. 程式人生 > >N皇后問題 回溯法

N皇后問題 回溯法

回溯法過程


在試探過程中,皇后的放置需要檢查她的位置是否和已經放置好的皇后發生衝突,因此需要一個檢查函式

假如兩個皇后被放置在(i,j)和(k,l)上 ,當且僅當 |i-k|==|j-l| 時兩個皇后在同一條對角線上。

(1).先從首位開始檢查,如果不能放置,則檢查該行的第二個位置,依次進行下去,直到找到一個可以放置皇后的位置,儲存當前狀態,然後轉下一行重複該操作。

(2).如果檢查該行所有位置均不能放置,說明上一行放置的皇后無法讓所有的皇后找到自己合適的位置。因此就要回溯到上一行,繼續檢查該皇后後面的位置。

附程式碼

#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
int ans = 0,queen[15];
int n,num[15];
int check(int x)     //用於檢查皇后是否可以放在此位置
{
	for(int i = 0;i<x;i++)
	{
		//queen[i] == queen[x] 用於保證元素不在同一列
		//abs(queen[i] == queen[x] == abs(n-i)) 用於約束元素不在同一行且不在同一條斜線上
		if(queen[i] == queen[x] || abs(queen[i] - queen[x]) == abs(x-i))
			return 0;
	}
	return 1;
}
//核心函式 回溯法思想
void NQUEEN(int x)  //回溯嘗試皇后的位置
{
	for(int i = 0;i<n;i++)
	{
		//首先將皇后放置在第0列的位置
		queen[x] = i;   //姜皇后擺在當前迴圈到的位置
		if(check(x))
		{
			if(x == n-1)
				ans++;   // 如果全都擺好,則ans++
			else
				NQUEEN(x+1); // 否則繼續擺下一個皇后
		}
	}
}
void init()  //一定要打表,不然會超時
{
	for(n = 1;n<=10;n++)
	{
		ans = 0;
		NQUEEN(0);    //從橫座標0開始嘗試
		num[n] = ans;
	}
}
int main()
{
	init();
	while(scanf("%d",&n))
	{
		if(n == 0)
			break;
		printf("%d\n",num[n]);
	}
}