基于Las Vegas 和回溯法的皇后问题(C语言描述),求N=12..20的最优StepVegas值

      算法采用多次执行这种QueenLV算法(100次),求取成功率。对于不同的N(12—20)皇后问题,记录随机放n(n<N)个皇后,算法成功一次需要的平均时间。

算法源代码(C描述):

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define N  12
#define RUN_TIME    100

enum boolean {false,true};

int x[N+1]={0};
int y[N+1]={0};

int randomi(int m,int n)
{
  int j;
  if(m > n)
  {
    printf("n must large than m!!!\n");
    return -1;
  }
  if(m==n)
    return n;
//  srand((unsigned)time(NULL));
  while(1)
  {
    j = rand();
    j %= n;
    if(j < m)
        j += n-m;
    else
        return j;
  }
}

int place(int k)
{
 int j;
 for(j=1;j<k;j++)
 {
   if((abs(k-j)==abs(x[j]-x[k])) || (x[j]==x[k]))
      return false;
 }
 return true;
}

void backtrack(int t)
{
 int i;
 if(t>N)
 {
   for(i=1;i<=N;i++)
     y[i]=x[i];
   return;
 }
 else
   for(i=1;i<=N;i++)
   {
    x[t]=i;
    if(place(t))
    {
      backtrack(t+1);
//      printf("in backtrace x[%d]=%d\n",t,x[t]); 
    }
   }
}

int QueensLV(int stopLV)
{
 int i,j,count=1,k=1;
 while((k <= stopLV) &&(count>0))
 {
   count=0;
   j=0;
   for(i=1;i<=N;i++)
   {
    x[k]=i;
    if(place(k))
    {
     count++;
     if(randomi(0,count)==0)
       j=i;
    }  
   }
   if(count>0)
     x[k++]=j;

//   for(i=1;i<k;i++)
//      printf("x[%d]=%d ",i,x[i]);
//   printf("\n(k) = %d\n",k);
 }
 if(count>0)
   return true;
 else
   return false;
}

int main(void)
{int dif_n,time_now,time_end;
 for(dif_n=0;dif_n<N;dif_n++)

 {int i,stop,j=0,sucess=0;
  printf("Please input the integer to stopLV and start backtrack(<=%d):",N);
  scanf("%d",&stop);
  time_now=clock();
  srand((unsigned)time(NULL));
  do{
         if(stop<N)
      {    
          while(!QueensLV(stop))
           ;
         }
    else
        QueensLV(stop);
      backtrack(stop+1);
    if(y[N]!=0)
    {
        sucess++;
        // printf("sucess = %d\n",sucess);
        for(i=0;i<=N;i++)
            y[i]=0;
    }
    j++;
    // printf("j=%d\n",j);
  }while( j<RUN_TIME);
//  printf("\n%d Queens's problem,y[%d]=",N,N);
//  for(i=1;i<=N;i++)
//    printf("%d ",y[i]);
//  printf("\n");
    printf("Run %d times,success %d times!, success rate is %3.0f%%\n",RUN_TIME,sucess, 100.0*sucess/RUN_TIME );
    time_end=clock();
    printf("it takes %ldms to solve this problem\n",(time_end-time_now)*1000/CLOCKS_PER_SEC/sucess);//输出成功一次的平均时间
    }

  return 0;
}

运行结果:

N=12时

N=20时

有运算结果可知:

1、纯回溯的方法成功率高,但耗时长;纯贪心LV成功率太低,采用stepVegas可以有效解决这个问题。在成功率满足需求的情况下可以大大缩短算法时间。

2、一半略少的皇后随机放置比较好。

原文地址:https://www.cnblogs.com/yuzeren48/p/2733653.html