题目的基本信息和基础,请先看上一篇八皇后非递归解法。
-
递归和非递归的区别:
1. 递归是让代码自动向下一层调用,回溯时回到之前的状态,所以这里就可以省略栈。
2. 递归可以一次性得到所有解,每次第7行放置成功后,就输出,然后往下一格试探,直到本行都不能放,就回溯到上一行。这样直到第一行全部试探完,所有解也就输出了。
-
技巧:
回溯的条件改变总是根据递归调用的句子对称,具体看代码就可以明白。所有回溯都是对称的。
-
代码:
# include <stdio.h> // 所有都是从0开始编号 // 在c语言中,给数组赋初值时,可以只写一个,这样后面的也就系统自动赋初值为此值 int col[8] = {0,0,0,0,0,0,0,0}; //第i列有没有放皇后,0表示没放,1表示放了 int left[15] = {0}; //左斜线i上有没有皇后,0表示没放,1表示放了 int right[15] = {0}; //右斜线i上有没有放皇后,0表示没放,1表示放了 int Q[8] = {-1}; //第i行第Q【i】列上放的皇后 void Queen(int i); void print(); int main (void){ // 递归:每一行找到了位置就递归调用下一行,如果这一行所有地方都不能放,就回溯回去往后找 Queen(0); print(); return 0; } void Queen(int i){ int j; for(j = 0; j < 8; j++){ if(!col[j] && !left[i+j] && !right[7+i-j]){ // 能放 // 放置皇后 Q[i] = j; // 修改状态 col[j] = 1; left[i + j] = 1; right[7+i-j] = 1; // 向下调用 if(i < 7 ) Queen(i+1); // 当i已经等于7,就不往下调用 else print(); // 当回溯回来时,需要把状态改回去(回溯的主要特点是:关于递归函数,对称) col[j] = 0; left[i + j] = 0; right[7+i-j] = 0; Q[i] = -1; } } } int cnt = 0; // 打印函数:打印方阵 void print() { int i,j; printf("第%d组解:\n",++cnt); for(i = 0; i < 8; i++){ for(j = 0; j < 8; j++){ if(Q[i] == j){ printf("Q "); }else { printf("x "); } } printf("\n"); } }
-
输出截图: