1. 程式人生 > >n皇后概率演算法與確定演算法折衷考慮最後解法

n皇后概率演算法與確定演算法折衷考慮最後解法


#include "pch.h"
#include <iostream>
#include <vector>
#include <random>
#include <ctime>
#include <time.h>
#include <set>
#include <sys/timeb.h>

using namespace std;

#define NUMOFQUEEN 20//12~20

//uniform返回1到x的一個數
static int seeds;
int uniform(int x) {
	uniform_int_distribution<int> u(1, x);
	default_random_engine e(seeds++);

	return u(e);
}

//回溯法求n皇后
bool backTrace2(int k, vector<int> tryV, set<int> &col, set<int> &diag45, set<int> &diag135, int &searchNode) {
	/*vector<int> tryV(1+NUMOFQUEEN);
	set<int> col, diag45,diag135;*/
	//求k到NUMOFQUEEN皇后怎麼放置,包括第k和第NUMOFQUEEN個皇后.
	int j = 1;
	while (k <= NUMOFQUEEN) {
		bool findJ = false;
		for (; j <= NUMOFQUEEN; ++j) {
			if (col.find(j) == col.end() && diag45.find(j - k) == diag45.end() && diag135.find(j + k) == diag135.end())
			{
				findJ = true;
				break;
			}
		}
		if (findJ) {
			++searchNode;
			tryV[k] = j;
			col.insert(j);
			diag45.insert(j - k);
			diag135.insert(j + k);
			++k;
			j = 1;
		}
		else {
			--k;
			j = tryV[k];
			if (j == 0)
				return false;
			tryV[k] = 0;
			col.erase(col.find(j));
			diag45.erase(diag45.find(j - k));
			diag135.erase(diag135.find(j + k));
			++j;

		}
	}
	if (k == 1 + NUMOFQUEEN) {
		return true;
	}
	else
		return false;
}

//隨機演算法求n皇后
bool QueensLV2(int &searchNode, int stepVegas) {
	set<int> col, diag45, diag135;//分別是已用的列、45度方向的行列之差、135度方向的行列之和
	vector<int> tryV(NUMOFQUEEN + 1);//(k,tryV[k})表示第k的皇后放置的位置
	int k = 0;//行號
	int j = 0;//列號
	//毫秒級時間戳,用於生成隨機數
	struct timeb tp;
	ftime(&tp);
	int seeds = tp.time / 1000 + tp.millitm;//隨機數初始種子

	while (k < stepVegas) {

		int nb = 0;//nb表示當前行可以放置的位置數目
		for (int i = 1; i <= NUMOFQUEEN; ++i) {
			if (col.find(i) == col.end() && diag45.find(i - k - 1) == diag45.end() && diag135.find(i + k + 1) == diag135.end()) {
				++nb;
				if (uniform(nb) == 1)//從nb的位置中隨機返回一個
					j = i;
			}
		}
		if (nb > 0) {
			k++;
			tryV[k] = j;//將列號記錄下來
			col.insert(j);
			diag45.insert(j - k);
			diag135.insert(j + k);
			++searchNode;//搜尋節點增加
		}
		if (nb == 0)
			break;
	}


	if (k == stepVegas) {
		return(backTrace2(k + 1, tryV, col, diag45, diag135, searchNode));
	}
	else
		return false;

}
int main() {

	struct timeb tp;
	ftime(&tp);
	seeds = tp.millitm + tp.time / 1000;

	cout << "n="<<NUMOFQUEEN<<"\nstepVegas	s		p		t(ms)\n";
	
	int stepVegas = 0;
	for (; stepVegas <= NUMOFQUEEN; ++stepVegas) {
		int sum = 0;
		int searchNode = 0;
		int j = 0;
		clock_t start, finish;
		double totaltime;
		start = clock();//開始時鐘
		for (int i = 0; i < 10; ++i) {
			while (!QueensLV2(searchNode, stepVegas))
				++j;

		}
		finish = clock();//結束時鐘
		totaltime = (double)(finish - start);
		sum += searchNode;
		cout << stepVegas << "		" << sum / 10.0 << "		" << 1.0 - j / (10.0 + j) << "		" << totaltime << endl;
	}

	return 0;
}