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