20皇后的不是很正確的解法

// HomeWork_P72.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//

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

using namespace std;


#define NUMOFQUEEN 20//12~20

//檢查是否合法
bool isOk(int x, int y, vector<vector<int>> chessBox) {
	
	//檢查列
	for (int i = 0; i < NUMOFQUEEN; ++i)
		if (chessBox[i][y] == 1)
			return false;
	//檢查135度和45度方向
	for(int i=0;i< NUMOFQUEEN;++i)
		for (int j = 0; j < NUMOFQUEEN; ++j) {
			if (chessBox[i][j] == 1) {
				if (i - j == x - y || i + j == x + y)
					return false;
			}
		}
	return true;
}
//回溯法求八皇后
void backTrack(vector<vector<int>> &chessBox) {
	int i = 0, j = 0;
	vector<int> stack;//保存列號
	int searchNode = 0;//搜索節點數
	while (i < NUMOFQUEEN) {
		bool findJ = false;
		for (; j < NUMOFQUEEN; ++j)
			if (isOk(i, j, chessBox)==true) {
				findJ = true;
				break;
			}
		if (findJ) {
			chessBox[i][j] = 1;//放置皇后
			++searchNode;
			stack.push_back(j);//將當前列入棧
			++i;
			j = 0;
		}
		else {
			--i;
			j = *(--stack.end());//回溯到上一行j
			stack.pop_back();//列出棧
			chessBox[i][j] = 0;
			j++;//從當前列的下一列開始
		}
	}
	cout << "搜索節點數: " << searchNode << endl;
}
//打印結果
void print(vector<vector<int>> chessBox) {
	for (auto ii : chessBox) {
		for (auto jj : ii) {
			cout << jj;
		}
		cout << endl;
	}
}
//uniform(0...n)從一個容器中隨機返回一個數
int uniform(vector<int> v) {
	uniform_int_distribution<int> u(0, v.size() - 1);
	default_random_engine e(time(0));//不能用秒級的
	return v[u(e)];
}
//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);
}
//LV貪心算法,求八皇后問題
void QueensLV()
{
	
	vector<int> col, diag45, diag135;//保存已用的列號、i+j、i-j;
	vector<int> tryV;//(i,try[i])表示第i個皇后放置的位置
	int searchNode = 0;//搜索節點數

	int i = 0;//行號
	int j = 0;//列號
	int nb =0;
	while (i < NUMOFQUEEN) {
		vector<int> okCol;//存放這一行中可以使用的列號
		 nb= 0;//nb的值爲第i個皇后可以放的位置總數
		for (int j2 = 0; j2 < NUMOFQUEEN; ++j2) {//查找這一行中能夠用的j
			if ((find(col.begin(), col.end(), j2) == col.end()) && (find(diag45.begin(), diag45.end(), i+j2) == diag45.end())&& (find(diag135.begin(), diag135.end(),i-j2) == diag135.end())){
				okCol.push_back(j2);
				
				nb++;

			}
		}
		if(okCol.size()>0)
			j = uniform(okCol);
		if (nb > 0) {//表示這一行可以放置皇后
			tryV.push_back(j);
			col.push_back(j);
			diag135.push_back(i - j);
			diag45.push_back(i + j);
			++i;
			++searchNode;
		}
		if (nb == 0) {//當前方法沒辦法放置所有皇后,就重置集合,從頭開始重來
			
			diag45.clear();
			diag135.clear();
			col.clear();
			i =j= 0;
			tryV.clear();
		}
	} 


	//打印
	for (auto ii = 0; ii < NUMOFQUEEN; ++ii) {
		for (auto jj = 0; jj < NUMOFQUEEN; ++jj)
			if (tryV[ii] == jj)
				cout << "X";
			else
				cout << "O";
		cout << endl;
	}
	cout << "搜索節點數:" << searchNode << endl;
}
//
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;

		}
	}
	//cout << k << endl;
	if (k == 1+NUMOFQUEEN) {
		//for (auto ii : tryV)
			//cout << ii << " ";
		//cout << endl;
		return true;
	}
	else
		return false;
}

//第二個隨機算法
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) {
		if(backTrace2(k + 1, tryV, col, diag45, diag135,searchNode))
			return true;
		else return false;
		
	}
	else
		return false;

}

void printV(vector<int> v){
	for (auto i : v)
		cout << i << " ";
	cout << endl;
}
int main() {
	clock_t start, finish;
	double totaltime;
	start = clock();//開始時鐘
	
	struct timeb tp;
	ftime(&tp);
	seeds = tp.millitm + tp.time / 1000;

	
	cout << "stepVegas		s		p\n";
	
		
	
		int stepVegas = 0;
		for (; stepVegas <= NUMOFQUEEN; ++stepVegas) {
			int sum = 0;
			int searchNode = 0;
			int j = 0;
			for (int i = 0; i < 100; ++i) {

				while (!QueensLV2(searchNode, stepVegas))++j;
			}
		sum += searchNode;
		cout << stepVegas << "		" << sum /100.0<<"		"<<j<< endl;
		}
	
	/*
	for (int i = 0; i < 100; ++i) {
		int searchNode = 0;
		while (!QueensLV2(searchNode, 20));
		cout << searchNode << endl;
	}*/
	//cout << searchNode << endl;
	



	finish = clock();//結束時鐘
	totaltime = (double)(finish - start) ;
	cout << "程序運行時間:" << totaltime << "毫秒" << endl;

	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章