拉斯维加斯算法求n皇后问题
#include <cstdlib>
#include <iostream>
using namespace std;
bool place(int x[],int k);
void queen(int n,int x[]);
void Output(int n,int x[]);
int main(int argc, char *argv[])
{
cout<<"请输入皇后的个数\n";
int n;
cin>>n;
int x[n+1];
x[0]=0;
cout<<"解向量是----\n";
queen(n,x);
system("PAUSE");
return EXIT_SUCCESS;
}
bool place(int x[],int k)
{
for(int i=1;i<k;i++)
if((x[i]==x[k])||(abs(x[i]-x[k])==abs(i-k)))
return 0;
return 1;
}
void queen(int n,int x[])
{
int k=1;
long num=0;
x[1]=0;
while(k>0)
{
x[k]+=1;
while((x[k]<=n)&&(!place(x,k)))
x[k]+=1;
if(x[k]<=n)
if(k==n)
{
num++;
Output(n,x);
}
else
x[++k]=0;
else
x[k--]=0;
}
system("PAUSE");
cout<<"一共有"<<num<<"种情况\n";
return;
}
void Output(int n,int x[])
{
cout<<"[";
for(int i=1;i<n;i++)
cout<<x[i]<<",";
cout<<x[n]<<"]"<<endl;
return;
}
一. 特征:
确定性算法的每一个计算步骤都是确定的,而随机算法允许算法在执行过程中随机地选择下一个计算步骤。在很多情况下,当算法在执行过程中面临一个选择时,随机性选择常比最优选择省时。因此随机算法可在很大程度上降低算法度。
拉斯维加斯算法不会得到不正确的解,但是有时找不到解。求得正确解的概率也依赖于算法所用的时间。
蒙特卡罗算法可求问题的精确解,但这个解不一定是正确的,求得正确解的概率也依赖于算法所用的时间。
二.原理
A.拉斯维加斯算法
通常采用bool型方法来表示拉斯维加斯算法。当算法找到一个解时返回true,否则false.
当返回false时,说明未得到解,那么可再次独立调用该算法,在时间允许的情况一直运算到出解为止。
B.蒙特卡罗算法
设P是一个实数,且0.5<p<1。如果蒙特卡罗算法对于问题的任一实例得到正确解的概率不小于P,则称该算法是p正确的。对于统一实例,蒙特卡罗算法不会给出两个不同的正确解答,则称该算法是一致的。而对于一个一致的p正确的蒙特卡罗算法,要提高获得正确解的概率,只要执行该算法若干次,并选择出现频率最高的解即可。
下面是用拉斯维加斯算法求解n皇后的程序

1 #include<iostream> 2 using namespace std; 3 class Queen{ 4 friend bool nQueen(int); 5 private: 6 bool Place(int k); //测试皇后K置于x[k]列的合法性 7 bool Backtrack(int t); //解n后问题的回溯法 8 bool QueenLV(int stopVegas); //随机放置n个皇后的拉斯维加斯算法 9 int n,*x,*y; 10 }; 11 bool Queen::Place(int k){ 12 for(int j=1;j<k;j++)//第k个皇后是否跟前面的皇后冲突 13 if((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k])) 14 return false; 15 return true; 16 } 17 bool Queen::Backtrack(int t){ 18 if(t>n){//存放皇后放置的位置 19 for(int i=1;i<=n;i++) 20 y[i]=x[i]; 21 return true; 22 } 23 else{ 24 for(int i=1;i<=n;i++){ 25 x[t]=i;//t皇后放在第i列 26 if(Place(t)&&Backtrack(t+1)) 27 return true; 28 } 29 } 30 return false; 31 } 32 bool Queen::QueenLV(int stopVegas){ 33 //随机放置n个皇后的拉斯维加斯算法 34 35 int k=1;//随机数产生器 36 int count=1; 37 //1<=stopVagas=<n表示允许随机放置的皇后数 38 while((k<=stopVegas)&&(count>0)){ 39 count=0; 40 for(int i=1;i<=n;i++){ 41 x[k]=i; 42 if(Place(k)) 43 y[count++]=i; 44 } 45 if(count>0) //如果能放置,则在这么多个能放置第k个皇后的位置中选择一个位置 46 x[k++]=y[rand()%count]; 47 } 48 return(count>0);//count>0表示放置成功 49 } 50 bool nQueen(int n){ 51 //与回溯法相结合的接n后问题的拉斯维加斯算法 52 Queen X; 53 X.n=n; 54 int *p=new int[n+1]; 55 int *q=new int[n+1]; 56 for(int i=0;i<=n;i++){ 57 p[i]=0; 58 q[i]=0; 59 } 60 X.y=p; 61 X.x=q; 62 int stop=5; 63 if(n>15) 64 stop=n-15; 65 bool found=false; 66 while(!X.QueenLV(stop));//直到能放置 67 //算法的回溯搜索部分 68 if(X.Backtrack(stop+1)){ 69 for(int i=1;i<=n;i++) 70 cout<<p[i]<<" "; 71 found=true; 72 } 73 cout<<endl; 74 delete []p; 75 delete []q; 76 return found; 77 } 78 int main(){ 79 int n; 80 cout<<"n:";cin>>n; 81 if(!nQueen(n)) 82 cout<<"无解"<<endl; 83 return 0; 84 }