八皇后算法

这个问题其实想好了怎么表示解就很好做了。 

static int g_eightqueen[8]={};
//这里用g_eightqueen[i]=n; 表示棋盘上第i行第n列为一个解(位置可用);
static int g_count = 0;

建立解的表示之后,就能比较轻松的写出代码了。八皇后算法是经典的利用回溯算法的问题,为便于理解,现在用递归实现回溯,理解后也可以用循环写。

一边想一边写的,代码还没测试。2333~

打印棋盘函数:

void show(void){
     int row,col;
     for(row=0; row<8; ++row){
         for(col=0; col<8; ++col){
             if(col = g_eightqueue[row])
                 printf("#");        //用#表示棋盘上该位置放置皇后
             else
                 printf(" ");
         }
         printf("\n");
     }
     printf("-------------------------\n");
}  

然后是寻找位置的函数,在寻找位置的时候,会将当前的位置与之前已确定可以放置的位置比较,以检查当前位置是否可行。因此还需要一个检查可行性的函数:

bool possible(int row; int index){  //表示当前将要放置的位置为第row行,第index列
    for(int valid=0; valid<row; ++valid){  //valid表示之前确认的那几行;
        if(index == g_eightqueue[valid])
            return false;   //
    }
    if(valid == row)   //能执行到这一步,说明for循环正常退出或者没有执行(当row=0时,随便放哪里都是正确的),即位置有效,if判断可以不写,此处为加强逻辑联系
        return true;
}

接下来就是回溯的主要代码了:

void seek(int row){
    if(row == 8){ //if判断也可以放在循环体里面,条件变成 row==7;
        show();
        g_count++;
        g_eightqueue[row] = 0;  //1.此处以及2.的置0意义,如果不置0会出现什么情况,结果有惊喜哦
        return ;
    }
    for(int index=0; index<8; ++index){
        if(possible(row,index)){
            g_eightqueue[row] = index;
            seek(row+1);     //找到一个合适位置后,就去下一行再找;递归
            g_eightqueue[row] = 0;  //2.
        }
    }
}

ok,万事大吉,写一个测试吧:

int main(void){
    eight(0);
    printf("g_count=%d\n",g_count);
    return 0;
}

最后给一个利用递归的回溯算法的框架:参考链接:http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741376.html

这个框架不够抽象,等我翻个更抽象的。

int a[n];
try(int i)
{
     if(i>n)
        输出结果;
      else
     {
        for(j = 下界; j <= 上界; j=j+1)  // 枚举i所有可能的路径
        {
            if(fun(j))                 // 满足限界函数和约束条件
              {
                 a[i] = j;
               ...                         // 其他操作
                 try(i+1);
               回溯前的清理工作(如a[i]置空值等);
               }
          }
      }
 }

以及非递归回溯算法实现框架(循环):

  int a[n],i;
 初始化数组a[];
 i = 1;
 while (i>0(有路可走)   and  (未达到目标))  // 还未回溯到头
 {
     if(i > n)                                              // 搜索到叶结点
     {   
           搜索到一个解,输出;
     }
     else                                                   // 处理第i个元素
     { 
           a[i]第一个可能的值;
           while(a[i]在不满足约束条件且在搜索空间内)
           {
               a[i]下一个可能的值;
           }
           if(a[i]在搜索空间内)
          {
               标识占用的资源;
               i = i+1;                              // 扩展下一个结点
          }
          else 
         {
               清理所占的状态空间;            // 回溯
               i = i –1; 
          }
 }

 

posted @ 2015-03-30 11:12  小白干  阅读(427)  评论(0编辑  收藏  举报