八皇后问题--回溯
2016-09-17 22:05
134 查看
在刘汝佳老师的书中对于8皇后问题的分析(我感觉非常经典):
8皇后问题可行的解:92个
回溯的定义: 当把问题分解成若干的步骤并递归的求解时候,如果当前步骤没有合法的选择,则函数将返回上一级递归调用,这种现象称为回溯。这是这个原因,递归枚举算法常被称为回溯法,应用十分普遍。
一共有3种思考的出发点:
从64个格子中选一个子集,使得"子集中恰好有8个格子,且任意两个选出的格子都不在同一行,同一列或同一对角线上",这正是子集的枚举问题。然而,64个格子的子集有264个,太大了,这并不是一个很好的模型
从64个格子中选8个格子,这是组合生成问题。根据组合数学,有c864 种方案,但是任然是不够好的
经过思考,不难发现以下的事实:恰好每行每列各放置一个皇后 。如果使用c[x]表示第x行皇后的列编号,则问题就变成了全排列问题。而0-7的全排列共有8!个,枚举的量是不会超过它。
上代码:
8皇后问题可行的解:92个
回溯的定义: 当把问题分解成若干的步骤并递归的求解时候,如果当前步骤没有合法的选择,则函数将返回上一级递归调用,这种现象称为回溯。这是这个原因,递归枚举算法常被称为回溯法,应用十分普遍。
下面是书中的代码:
书中的代码使用的是一位数据就解决的问题:
#include<iostream>
//使用一维数组解决问题
using namespace std;
int c[8];
int n=8; //代表的是8个皇后,同时是8维的棋盘
void search(int cur);
int tot = 0;
int main(){
search(0);
cout <<tot;
}
void search(int cur){//cur标志的是现在正在处理的是第几个皇后
if (cur == n){
tot ++; //tot代表的是可行解的总数量
}else{
for (int i=0; i<n; i++){ //对于每个皇后都要考虑一行的8个位置
int ok = 1;
c[cur] = i;
for (int j=0; j<cur; j++) //检查和前面的皇后是否冲突
if (c[cur]==c[j] || cur-c[cur]==j-c[j] || cur+c[cur]==j+c[j]){
ok = 0;
break;
}
if(ok)
search(cur+1);
}
}
}
8皇后问题可行的解:92个
回溯的定义: 当把问题分解成若干的步骤并递归的求解时候,如果当前步骤没有合法的选择,则函数将返回上一级递归调用,这种现象称为回溯。这是这个原因,递归枚举算法常被称为回溯法,应用十分普遍。
一共有3种思考的出发点:
从64个格子中选一个子集,使得"子集中恰好有8个格子,且任意两个选出的格子都不在同一行,同一列或同一对角线上",这正是子集的枚举问题。然而,64个格子的子集有264个,太大了,这并不是一个很好的模型
从64个格子中选8个格子,这是组合生成问题。根据组合数学,有c864 种方案,但是任然是不够好的
经过思考,不难发现以下的事实:恰好每行每列各放置一个皇后 。如果使用c[x]表示第x行皇后的列编号,则问题就变成了全排列问题。而0-7的全排列共有8!个,枚举的量是不会超过它。
上代码:
#include<iostream> #include<math.h> using namespace std; int a[8][8]; //相当于放置八个皇后的棋盘 int dfs(int n); //深度优先搜索 bool isOk(int m,int n); //判断(m,n)位置上是否可以放置一个皇后 int count = 0; //用于记录总的可行的解的数量 int main(){ dfs(0); cout << count; } int dfs(int n){ //第几层的皇后 if (n > 7){ for (int i=0; i<8; i++){ for (int j=0; j<8; j++) cout << " " << a[i][j]; cout << endl; } count++; cout << endl; return 0; } for (int i=0; i<8; i++){ if (isOk(n,i)){ //判断该位置是否可以放置 a [i] = (n+1); dfs(++n); --n; //考虑该行棋盘的其他位置的时候,将环境还原 a [i] = 0; } } } bool isOk(int m,int n){ if (a[m] == 0){ for (int i=0; i<8; i++){ for (int j=0; j<8; j++){ if (a[i][j] != 0){ if (abs(m-i) == abs(n-j)|| i==m || j==n) return false; } } } }else{ return false; } return true; }
8皇后问题可行的解:92个
回溯的定义: 当把问题分解成若干的步骤并递归的求解时候,如果当前步骤没有合法的选择,则函数将返回上一级递归调用,这种现象称为回溯。这是这个原因,递归枚举算法常被称为回溯法,应用十分普遍。
下面是书中的代码:
书中的代码使用的是一位数据就解决的问题:
#include<iostream>
//使用一维数组解决问题
using namespace std;
int c[8];
int n=8; //代表的是8个皇后,同时是8维的棋盘
void search(int cur);
int tot = 0;
int main(){
search(0);
cout <<tot;
}
void search(int cur){//cur标志的是现在正在处理的是第几个皇后
if (cur == n){
tot ++; //tot代表的是可行解的总数量
}else{
for (int i=0; i<n; i++){ //对于每个皇后都要考虑一行的8个位置
int ok = 1;
c[cur] = i;
for (int j=0; j<cur; j++) //检查和前面的皇后是否冲突
if (c[cur]==c[j] || cur-c[cur]==j-c[j] || cur+c[cur]==j+c[j]){
ok = 0;
break;
}
if(ok)
search(cur+1);
}
}
}
相关文章推荐
- 八皇后问题 回溯递归 C语言版
- 回溯法解八皇后问题
- 八皇后问题 --回溯
- 利用回溯的八皇后问题
- Queen 八皇后问题 回溯经典解法
- GDI+学习(7) 八皇后问题回溯算法演示系统
- 八皇后问题 DFS,回溯剪枝 //http://poj.grids.cn/practice/2698
- 八皇后问题(递归、非递归——回溯)
- C# 用回溯递归解决“八皇后”问题
- 八皇后问题、N皇后问题回溯法详解
- 【算法复习二】八皇后问题 ---- 回溯
- 【算法复习二】八皇后问题 ---- 回溯
- 回溯法解决八皇后和0,1背包问题和排列问题
- 回溯法-八皇后问题之C实现
- 八皇后问题回溯算法演示系统
- 八皇后问题 C#版本算法 回溯法
- 回溯算法---八皇后问题
- uva 11553 Grid Game (回溯- 类似,比八皇后问题简单)
- 回溯算法之八皇后问题
- C#WPF实现回溯算法解决八皇后问题