拉斯维加斯类型概率算法的一个显著特征是它所做的随机性选择有可能导致算法找不到问题的解,即算法运行一次,或者得到一个正确的解,或者无解。因此,需要对同一输入实例反复多次运行算法,直到成功地获得问题的解。
【问题描述】设计一个求解n皇后问题的拉斯维加斯型概率算法。
【问题求解】当在第i行放置一个皇后时,可能的列为1-n,产生1-n的随机数j,如果皇后的位置(i,j)发生冲突,继续产生另外一个随机数j,这样最多试探n次。其中任何一次试探成功(不冲突),则继续查找下一个皇后的位置,如果试探超过n次,算法返回false。对应的完整程序如下:
#include <iostream>
#include <stdlib.h> //包含产生随机数的库函数
#include <time.h>
#define N 20 //最多皇后个数
using namespace std;
int q[N]; //各皇后所在的列号,(i,q[i])为一个皇后位置
int num = 0; //累计调用的个数
void dispasolution(int n) { //输出n皇后问题的一个解
cout << "第" << num << "次运行找到一个解:" << endl;
for (int i = 1; i <= n;i++) {
cout << i << q[i];
}
cout << endl;
}
int randa(int a, int b) { //产生一个[a,b]的随机数
return rand() % (b - a + 1) + a;
}
bool place(int i,int j) { //测试(i,j)为位置能否摆放皇后
if (i==1) { //第一个皇后总是可以放置
return true;
}
int k = 1;
while (k<i) { //k=1~i-1是已放置了皇后的行
if ((q[k]==j)||(abs(q[k]-j)==abs(i-k))) {
return false;
}
k++;
}
return true;
}
bool queen(int i,int n) { //放置1~i的皇后
int count, j;
if (i>n) {
dispasolution(n); //所有皇后放置结束
return true;
}
else {
count = 0; //试探次数累计
while (count<=n) {//最多试探n次
j = randa(1, n); //产生第i行上1到n列的一个随机数j
count++;
if (place(i,j)) { //在第i行上找到一个合适位置(i,j)
break;
}
}
if (count>n) {
return false;
}
q[i] = j;
queen(i + 1, n);
}
}
void main() {
int n = 6; //n为存放实际皇后个数
cout << n << "皇后问题求解如下:" << endl;
srand((unsigned)time(NULL)); //随机种子
while (num<10) {
if (queen(1,n)) { //找到一个解退出
break;
}
num++;
cout << "第" << num << "次运行没有找到解" << endl;
}
system("pause");
}
输出结果:
6皇后问题求解如下:
第1次运行没有找到解
第2次运行没有找到解
第3次运行没有找到解
第4次运行没有找到解
第5次运行没有找到解
第6次运行没有找到解
第7次运行没有找到解
第8次运行没有找到解
第9次运行没有找到解
第10次运行没有找到解
请按任意键继续. . .
6皇后问题求解如下:
第1次运行没有找到解
第2次运行没有找到解
第3次运行没有找到解
第4次运行没有找到解
第4次运行找到一个解:
(1,3)(2,6)(3,2)(4,5)(5,1)(6,4)
请按任意键继续. . .