1. 程式人生 > >八皇后問題(回溯的演算法)

八皇后問題(回溯的演算法)

八皇后問題是經典的回溯演算法案例,但是對初學者有點難以理解...

 

 

 

基本思路是,從第一個皇后開始放置,同時設定列和左斜和右斜放置標誌(如果是從列開始的就設定行的標誌)

 

 

第i行遍歷,如果沒有能夠放的位置,直接退出函式(也就是不用管),如果沒有放到8個,就呼叫下一個函式,但是仍然在這一級函式之內,所以後續需要回溯以便進行下一個點的搜尋。

 

 

這樣是按照第一行從第一個字開始的輸出,如果按列的話,轉置矩陣2333333,程式碼如下:

/*
經典回溯
八皇后問題
按照每一行開始搜尋
by Dr.ls
*/
#include<iostream>
using namespace std;
const int size = 9;
int num = 0;
int q[9];//記錄每個行的皇后佔用的列號
bool line[9];//所在列
bool zuo[17];//所在左斜線i+j
bool you[17];//右斜線
void set(int i)
{
	int j, k, m;
	for (j = 1; j <= 8; j++)
	{
		if ((line[j] == true) && (you[i - j + 9] == true) && (zuo[i + j] == true))
		{
			q[i] = j;//佔用ij位置
			line[j] = false;
			you[i - j + 9] = false;
			zuo[i + j] = false;//所在列,斜線均被佔用
			if (i < 8)//未到最後一行就呼叫下一行的函式放置
			{
				set(i + 1);
			}
			else			              // 如果已經放完8個皇后
			{
				num++;		             // 方案數加1
				cout << num << endl;   // 輸出方案號
				char zz[17][17];
				for (m = 1; m <= 8; m++)
				{
					for (k = 1; k <= 8; k++)
					{
						if (k == q[m])
						{
							zz[m][k] = '*';
						}
						else if (k != q[m])
						{
							zz[m][k] = '.';
						}
					}
				}//畫棋盤
				for (k = 1; k <= 8; k++)
				{
					for (m = 1; m <= 8; m++)
					{
						cout << ' ' << zz[k][m];
					}
					cout << endl;//輸出結果
				}
			}
			line[j] = true;
			you[i - j + 9] = true;
			zuo[i + j] = true;//回溯演算法,裝作無事發生
		}
	}
}
int main()
{
	int i;
	num = 0;
	for (i = 1; i <= 8; i++)
	{
		line[i] = true;
	}
	for (i = 1; i <= 16; i++)
	{
		zuo[i] = true;
		you[i] = true;
	}
	set(1);//從第一行開始放
	return 0;
}