标签:
这个问题其实想好了怎么表示解就很好做了。
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; } }
标签:
原文地址:http://www.cnblogs.com/young8848/p/4377488.html