LV算法和回溯法结合解n后问题

我的算法作业:n=12 ~ 20时,求出较优的stopVegas值。(也就随机放置几个皇后比较好的问题)。

解答:(VC6.0下调试通过,可能某些统计数据的计算部分,有不太妥当的地方,贴出来也就是有高手能给指点一下)

/**

*EX8:

*     LV算法与回溯法相结合,解n皇后问题。求n=12~20时最优的StepVegas

*/

#include

#include

#include//随机函数的种子

using namespace std;

 

#define AVG 200//产生200个正确的解,然后再统计相关数据

 

int failure=0; //算法运行失败的次数

int success=0; //算法运行成功的次数

 

 

int nsnode=0; //一次成功搜索访问的结点数

int nfnode=0; //一次不成功搜索访问的结点数

 

int tempLVNode=0;

int tempBackNode=0;

 

class RandomNumber

{

public:  int Random(int n)

       {//生成0 ~ n-1之间的随机整数,n不大于32767

              if(n>32767)

              {

                     cout<<"您输入的n值不能大于32767"<

                     exit(-1);

              }

 

              int x;

              x=rand();

              return x%n;

       }

};

 

class Queen

{

       friend void nQueen(int);

public:

       Queen(int n);

       bool Place(int k);         //测试皇后k置于第x[k]列的合法性,  注意:x[k]的值可以取从1n

       bool Backtrack(int t);    //n后问题的回溯法

       bool QueensLV(int stopVegas);    //随机放置stopVegas个皇后的LV算法  

       int n,*x,*y;                  //x,y 是解向量

 

};

 

Queen::Queen(int m)

{

       n=m;

}

 

 

bool Queen::Place (int k)

{

       for(int j=1;j

       {

              if((abs(k-j) == abs(x[k]-x[j])) || (x[j]==x[k]))

                     return 0;

       }

 

       return 1;

}

 

bool Queen::Backtrack (int t)

{

      

       if(t>n)

       {

              for(int i=1;i<=n;i++)

                     y[i]=x[i];

 

              return 1;

       }

       else

       {

              for(int i=1;i<=n;i++)

              {

                     x[t]=i;

                    

                     if(Place(t) && Backtrack(t+1)) //要理解回溯法的精髓

                     {

                            tempBackNode++;

                            return 1;

                     }

              }

 

       }

      

       tempBackNode++;//某皇后放置失败

       return 0;

}

 

bool Queen::QueensLV (int stopVegas)

{

       RandomNumber rnd;           //随机数生成器

       int k=1;                       //从第1个皇后开始放置

       int count=1;

 

       tempLVNode=0;

 

       while((k<=stopVegas) && (count>0))

       {

              count=0;

              for(int i=1;i<=n;i++)

              {

                     x[k]=i;

              //     tempLVNode++;

                     if(Place(k))

                            y[count++]=i; //数组y中存放的是放置皇后k,可用的列号,以便于等会随机选择第k个皇后的位置

              }

 

              if(count>0)

              {//皇后k可以找到一个随机放置的位置

                     int r=rnd.Random(count);

                     x[k++]=y[r];   //随机选择一列放置皇后k,然后k++,继续while循环

                     tempLVNode++;

              }

              else

              {//皇后k找不到随机放置的位置,QueensLv算法失败

 

              }

       }

 

       return (count>0);  //表示放置成功

}

 

void nQueen(int n,int stopVegas)

{

       Queen X(n);

       //初始化X

       int *p=new int[n+1];

 

       for(int i=0;i<=n;i++)

       {

              p[i]=0;

       }

 

       X.y=p;

      

 

 

       failure=0;      //算法运行失败的次数

       success=0;      //算法运行成功的次数

      

       nsnode=0;      //一次成功搜索访问的结点数

       nfnode=0;      //一次不成功搜索访问的结点数

      

       while(1)

       {

              while(1)

              {

                     if(!X.QueensLV(stopVegas))

                     {//说明随机放置部分算法失败

                            nfnode+=tempLVNode;

                     //     nsnode+=tempLVNode;

                            failure++;

       //                   cout<<"LV搜索失败,算法重新搜索...."<

                     }

                     else

                     {//随机放置部分算法成功,但还不能保证整个算法运行成功,还要看回溯部分是否成功,才能确定算法成功

       //                   cout<<"LV随机放置完毕"<

                            break;     //推出while循环,开始回溯

                     }

              }//while.....LV的循环搜索,直到成功为止

             

              //算法回溯部分

       //     cout<<"开始回溯..."<

              tempBackNode=0;

              if(X.Backtrack(stopVegas+1))

              {//回溯搜索成功

       //            cout<<"回溯成功,"<皇后问题找到正确解。"<

                     nsnode+=tempLVNode;//LV算法部分搜索的结点数也要算在其内

                     nsnode+=tempBackNode;

                     success++;

 

 

 

                     if(success>=AVG)

                            break;

              }

              else

              {//回溯部分搜索失败,这也是由随机放置皇后的算法运行的结果导致的失败

                     failure++;

                     nfnode+=tempLVNode;

                     nfnode+=tempBackNode;

       //            cout<<"回溯失败!!"<

              }

       }//while.....LV成功后,若回溯失败,则继续循环搜索,直到成功AVG次为止,然后求平均值

      

}

 

 

int main()

{

       int n,stopVegas,Beststop;

       float p,s,e,t;

       float tArray[21];

       srand(time(0));//为随机数的生成选定种子

      

       /***********实现结果向文件中输出**********************/

       FILE *fp;       //声明文件指针

       fp=fopen("result.txt","a+");//新建文件,文件名自定,保存路径自定注意/必须为//转义字符

       if(!fp)

       {

              printf("File Open ERROR!");

              exit(-1);

       }

 

 

       for(n=8;n<=20;n++)

       {     

              fprintf(fp,"/nstopVegas/tp/t/ts/t/te/t/tt/n");

 

              for(stopVegas=0;stopVegas<=n;stopVegas++)

              {

                     nQueen(n,stopVegas);

                    

                     p=(float)success/(success+failure);

                     s=(float)nsnode/success;                     //一次  成功搜索访问的结点数平均值s

                     if(failure==0)                                    //一次不成功搜索访问的结点数平均值e

                     {

                            e=0;

                                         

                     }

                     else

                     {

                            e=(float)nfnode/failure;

                     }

 

                     tArray[stopVegas]=s+((1-p)*e)/p;  //反复调用算法使得最终找到一个解所访问的结点数的平均 值t

                     fprintf(fp,"/n%d/t/t%f/t%f/t%f/t%f/n",stopVegas,p,s,e,tArray[stopVegas]);

              }

              //找出t值最小的stopVegas

              t=tArray[0];

              for(int m=1;m<=n;m++)

              {

                     if(tArray[m]

                     {

                            t=tArray[m];                              

                            Beststop=m;

                     }

              }

             

              cout<<"n="<时,算法效率很高。"<

             

             

              fprintf(fp,"/nn=%d时,取stopVegas=%d时,算法效率很高/n",n,Beststop);     //文件输出结果

             

       }

 

       fclose(fp);

       return 1;

}

 

调试运行后的结果:

stopVegas p       s                    e                t

0  1.000000 261.000000 0.000000 261.000000

1  1.000000 305.484985 0.000000 305.484985

2  1.000000 182.050003 0.000000 182.050003

3  0.990099 141.414993 777.000000 149.184998

4  0.833333 66.205002 147.925003 95.790009

5  0.505050 33.435001 45.413265 77.940002

6  0.247831 19.650000 20.449753 81.714996

7  0.126502 14.885000 13.321507 106.870003

8  0.074377 12.930000 10.930896 148.964996

9  0.057803 12.225000 10.103681 176.914993

10  0.046751 12.070000 9.625797 208.340012

11  0.051626 12.000000 9.360642 183.955002

12  0.045798 12.000000 9.224622 204.194992

当n=12时,取stopVegas=5时,算法效率很高

stopVegas p  s  e  t

0  1.000000 111.000000 0.000000 111.000000

1  1.000000 305.790009 0.000000 305.790009

2  1.000000 259.345001 0.000000 259.345001

3  1.000000 201.509995 0.000000 201.509995

4  0.934579 120.699997 432.357147 150.964996

5  0.692042 64.209999 117.359550 116.434998

6  0.410678 29.584999 39.655052 86.489998

7  0.214362 19.469999 19.836288 92.169991

8  0.104167 15.275000 13.603488 132.264999

9  0.075301 13.920000 11.569219 155.990005

10  0.055479 13.320000 10.725991 195.930008

11  0.050594 13.050000 10.410072 208.395004

12  0.043908 13.000000 10.114351 233.239990

13  0.045882 13.000000 10.035105 221.680008

当n=13时,取stopVegas=6时,算法效率很高

stopVegas p  s  e  t

0  1.000000 1899.000000 0.000000 1899.000000

1  1.000000 1338.555054 0.000000 1338.555054

2  1.000000 466.649994 0.000000 466.649994

3  1.000000 380.614990 0.000000 380.614990

4  0.990099 201.800003 883.000000 210.630005

5  0.851064 119.370003 304.057129 172.579987

6  0.576369 54.790001 90.217690 121.100006

7  0.303030 31.410000 35.563042 113.204994

8  0.156863 21.855000 19.395350 126.104996

9  0.087873 16.815001 14.168112 163.880005

10  0.064205 15.020000 12.321097 194.599991

11  0.045015 14.315000 11.590384 260.204987

12  0.039960 14.075000 11.206244 283.304993

13  0.031294 14.000000 10.960103 353.269989

14  0.035753 14.000000 10.856507 306.800018

当n=14时,取stopVegas=7时,算法效率很高

stopVegas p  s  e  t

0  1.000000 1359.000000 0.000000 1359.000000

1  1.000000 1333.415039 0.000000 1333.415039

2  1.000000 712.780029 0.000000 712.780029

3  1.000000 413.035004 0.000000 413.035004

4  0.995025 333.635010 4825.000000 357.760101

5  0.970874 148.339996 1107.000000 181.550018

6  0.833333 95.294998 218.925003 139.080002

7  0.531915 47.345001 73.909088 112.385002

8  0.263852 29.610001 33.044804 121.805008

9  0.149142 20.975000 18.622261 127.215004

10  0.087336 17.459999 14.520096 169.195007

11  0.056754 16.070000 12.978039 231.765015

12  0.035702 15.350000 12.331729 348.429993

13  0.034941 15.035000 12.044895 347.714996

14  0.039185 15.000000 11.800775 304.354980

15  0.032992 15.000000 11.689355 357.614990

当n=15时,取stopVegas=7时,算法效率很高

stopVegas p  s  e  t

0  1.000000 10052.000000 0.000000 10052.000000

1  1.000000 4528.399902 0.000000 4528.399902

2  1.000000 2248.639893 0.000000 2248.639893

3  1.000000 934.989990 0.000000 934.989990

4  1.000000 387.359985 0.000000 387.359985

5  0.990099 322.769989 2192.500000 344.694977

6  0.913242 195.020004 601.000000 252.115021

7  0.760456 93.080002 196.857147 155.090012

8  0.480769 51.959999 63.550926 120.595001

9  0.238095 29.684999 31.593750 130.785004

10  0.129618 22.059999 19.131794 150.529999

11  0.074599 18.594999 15.299476 208.384995

12  0.058360 16.870001 13.639604 236.945007

13  0.041815 16.400000 13.204452 318.980011

14  0.037559 16.040001 12.841951 345.114990

15  0.029656 16.000000 12.645630 429.765015

16  0.031666 16.000000 12.573904 400.509979

当n=16时,取stopVegas=8时,算法效率很高

stopVegas p  s  e  t

0  1.000000 5374.000000 0.000000 5374.000000

1  1.000000 4551.089844 0.000000 4551.089844

2  1.000000 2576.129883 0.000000 2576.129883

3  1.000000 1339.150024 0.000000 1339.150024

4  1.000000 745.065002 0.000000 745.065002

5  1.000000 431.035004 0.000000 431.035004

6  0.990099 277.704987 1972.000000 297.424988

7  0.917431 164.065002 489.944458 208.160019

8  0.671141 94.169998 145.571426 165.499985

9  0.390625 44.290001 58.509617 135.565002

10  0.216216 30.620001 29.394484 137.175003

11  0.120337 22.625000 19.341312 164.009995

12  0.067249 19.299999 15.890411 239.699997

13  0.048054 18.120001 14.560575 306.565002

14  0.033490 17.434999 14.013514 421.864990

15  0.029197 17.049999 13.713082 473.009979

16  0.028514 17.000000 13.479160 476.234985

17  0.027349 17.000000 13.431042 494.674988

当n=17时,取stopVegas=9时,算法效率很高

stopVegas p  s  e  t

0  1.000000 41299.000000 0.000000 41299.000000

1  1.000000 13972.054688 0.000000 13972.054688

2  1.000000 8674.644531 0.000000 8674.644531

3  1.000000 2865.405029 0.000000 2865.405029

4  1.000000 1729.319946 0.000000 1729.319946

5  1.000000 873.065002 0.000000 873.065002

6  0.995025 551.669983 3748.000000 570.410034

7  0.975610 234.690002 887.200012 256.869995

8  0.829876 151.880005 362.731720 226.240005

9  0.677966 77.199997 116.978951 132.764999

10  0.337268 47.680000 52.053436 149.965012

11  0.195122 30.070000 27.648485 144.120010

12  0.097371 23.350000 19.790722 206.809998

13  0.069493 20.360001 16.656834 243.394989

14  0.041331 19.150000 15.380255 375.894989

15  0.030211 18.250000 14.868536 495.529999

16  0.025313 18.065001 14.537593 577.835022

17  0.025562 18.000000 14.379591 566.150024

18  0.022287 18.000000 14.292227 645.000000

当n=18时,取stopVegas=9时,算法效率很高

stopVegas p  s  e  t

0  1.000000 2545.000000 0.000000 2545.000000

1  1.000000 7410.785156 0.000000 7410.785156

2  1.000000 5709.879883 0.000000 5709.879883

3  1.000000 3959.875000 0.000000 3959.875000

4  1.000000 2243.580078 0.000000 2243.580078

5  1.000000 1375.560059 0.000000 1375.560059

6  1.000000 742.315002 0.000000 742.315002

7  0.990099 465.059998 2018.000000 485.239990

8  0.938967 269.089996 1025.153809 335.725037

9  0.865801 175.294998 315.612915 224.214996

10  0.586510 74.089996 109.212769 151.085007

11  0.329489 48.935001 50.051598 150.790009

12  0.189934 30.629999 28.412661 151.809998

13  0.095923 24.379999 20.492308 217.520004

14  0.055882 21.110001 17.289139 313.209991

15  0.041017 20.115000 16.178144 398.360016

16  0.030125 19.295000 15.677589 524.034973

17  0.026532 19.075001 15.389207 583.705017

18  0.023395 19.000000 15.225296 654.579956

19  0.023384 19.000000 15.148211 651.665039

当n=19时,取stopVegas=11时,算法效率很高

stopVegas p  s  e  t

0  1.000000 199635.000000 0.000000 199635.000000

1  1.000000 77260.320313 0.000000 77260.320313

2  1.000000 29588.974609 0.000000 29588.974609

3  1.000000 9577.155273 0.000000 9577.155273

4  1.000000 5345.165039 0.000000 5345.165039

5  1.000000 2152.679932 0.000000 2152.679932

6  1.000000 1297.714966 0.000000 1297.714966

7  1.000000 748.434998 0.000000 748.434998

8  0.980392 408.489990 1769.750000 443.884979

9  0.900901 224.020004 880.772705 320.904999

10  0.760456 153.759995 253.730164 233.684998

11  0.507614 82.434998 98.329895 177.815002

12  0.289855 45.945000 45.008163 156.215012

13  0.138313 32.610001 27.672552 205.009995

14  0.106952 25.660000 20.958683 200.665009

15  0.052466 22.340000 18.233112 351.630005

16  0.033383 21.000000 16.993784 513.055054

17  0.025790 20.285000 16.505362 643.775024

18  0.027847 20.075001 16.294043 588.900024

19  0.024292 20.000000 16.113781 667.210022

20  0.020309 20.000000 16.045502 794.035034

当n=20时,取stopVegas=12时,算法效率很高

 

你可能感兴趣的:(C++,算法)