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);
}

bool backTrace3(int stepvegas, int &searchNode, int tryV[], bool col[], bool diag45[], bool diag135[]);
//随机算法求n皇后
bool QueensLV2(int &searchNode, int stepVegas) {
	int tryV[NUMOFQUEEN + 1];
	bool col[NUMOFQUEEN + 1];
	bool diag45[NUMOFQUEEN + NUMOFQUEEN + 2];
	bool diag135[NUMOFQUEEN + NUMOFQUEEN + 2];
	memset(col, false, sizeof(col));
	memset(diag45, false, sizeof(diag45));
	memset(diag135, false, sizeof(diag135));
	//分别是已用的列、45度方向的行列之差、135度方向的行列之和
	//(k,tryV[k})表示第k的皇后放置的位置
	int k = 1;//行号
	int j = 1;//列号
	while (k <= stepVegas) {

		int nb = 0;//nb表示当前行可以放置的位置数目
		for (int i = 1; i <= NUMOFQUEEN; ++i) {
			if (!col[i] && !diag45[k + i] && !diag135[NUMOFQUEEN + (k - i)]) {
				++nb;
				if (uniform(nb) == 1)//从nb的位置中随机返回一个
					j = i;
			}
		}
		if (nb > 0) {
			tryV[k] = j;//将列号记录下来
			col[j] = true;
			diag45[k + j] = true;
			diag135[NUMOFQUEEN + (k - j)] = true;
			++k;
			++searchNode;//搜索节点增加
		}
		if (nb == 0)
			break;
	
	}
	if (k == stepVegas+1) {
		return(backTrace3(k, searchNode, tryV, col, diag45, diag135));
	}
	else
		return false;

}


//回溯法求n皇后
bool backTrace3(int stepvegas,int &searchNode,int tryV[],bool col[],bool diag45[],bool diag135[]) {

	int k = stepvegas;
	//求k到NUMOFQUEEN皇后怎么放置,包括第k和第NUMOFQUEEN个皇后.
	int j = 1;
	while (k <= NUMOFQUEEN) {
		bool findJ = false;
		for (; j <= NUMOFQUEEN; ++j) {
			if (!col[j]&&!diag45[k+j]&&!diag135[NUMOFQUEEN+(k-j)])
			{
				findJ = true;
				break;
			}
		}
		if (findJ) {
			++searchNode;
			tryV[k] = j;
			col[j]=true;
			diag45[k + j] = true;
			diag135[NUMOFQUEEN+(k - j)] = true;
			++k;
			j = 1;
		}
		else {
			--k;
			j = tryV[k];
			tryV[k] = 0;
			col[j] = false;
			diag45[k+j]= false;
			diag135[NUMOFQUEEN+k-j]= false;
			++j;
		}
	}
	for (int kkk = 1; kkk <= NUMOFQUEEN; ++kkk)
		cout << tryV[kkk] << " ";
	if (k == 1 + NUMOFQUEEN) {
		return true;
	}
	else
		return false;
}

int main() {
	//毫秒级时间戳,用于生成随机数
	struct timeb tp;
	ftime(&tp);
	seeds = tp.time / 1000 + tp.millitm;//随机数初始种子
	cout << "stepvegas	searchNode	p		t(us)\n";
	for (int i = 0; i <= NUMOFQUEEN; ++i) {
		int sn = 1;
		int sp = 0;
		clock_t start, finish;
		double totaltime;
		start = clock();//开始时钟
		for(int j=0;j<1000;++j)
			while (!QueensLV2(sn, i))++sp;
		finish = clock();
		totaltime = (finish-start)*1.0;
		cout << i << "		" << sn / 1000.0 << "		 " << 1000.0 / (1000.0 + sp) <<"            "<<totaltime<< endl;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值