经典算法问题-01-八皇后
来源:互联网 发布:淘宝退款成功后收到货 编辑:程序博客网 时间:2024/06/03 20:52
八皇后问题
问题描述:
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
简化问题:
由于八皇后问题的正确答案为92种排列方案,由于正确的棋子放置方式实在太多,难以一一列举,所以先简化问题,解决四皇后的排列,即将8×8棋局改为4×4棋局,规则不变
建立模型:
要使用C++解决这个问题,首先要建立模型,让问题能够使用数学和C++的控制语句来解决。
将棋盘模拟为一个坐标轴,使用一个数组index将每个棋子定位到坐标轴中,index数组的下标为横坐标值,index[i]的值为纵坐标值,如下图所示,index[0] = 1 ; index[1] = 4 ; index[2] = 2 ; index[3] = 3
方案1—-枚举法:
将所有可能的棋子放置情况全部列举出来,一一判断是否合乎条件
C++程序:
#include<iostream>using namespace std;//判断棋子放置方式是否正确bool Judge(int *index, int i) { for (int i = 0; i < 4; i++){ for (int j = i + 1 ; j < 4; j++) { //判断棋子是否在同一行,或某一对角线上 //1,横坐标不同 i与j不相等 //2,纵坐标不同 index[i]与index[j]不相等 //3,不在同一对角线 index[i]- index[j]的绝对值和j-i的绝对值不相等 if (index[i] == index[j] || abs(index[i]- index[j])==j-i){ return false; } } } return true;}//打印正确的棋子放置方式void Sloution(int *index) { cout << "四皇后问题的一种正确解法,横坐标从0到4的4列上,纵坐标的值依次是:"; for (int i = 0; i < 4; i++){ cout << index[i]; } cout << endl;}int main() { int index[8]; //多层循环,穷举每一种放置方式 for (index[0] = 1; index[0] <= 4 ; index[0]++){ for (index[1] = 1; index[1] <= 4; index[1]++) { for (index[2] = 1; index[2] <= 4; index[2]++) { for (index[3] = 1; index[3] <= 4; index[3]++) { //判断棋子放置是否合乎规则,正确则打印,不正确则继续 if (Judge(index,4)){ Sloution(index); } else { continue; } } } } } cin.get(); return 0; }
上述程序使用了4个for循环来模拟所有可能出现的棋子放置情况,Judge()方法用来判断是否合乎条件
运行结果:
正确结果的演示:
纵坐标:2413
纵坐标:3142
枚举法的优化:
枚举法解决此四皇后问题需要的循环次数太多,四皇后需要4X4X4X4次遍历,才能将所有可能的情况列举出来,八皇后更是要8X8X8X8X8X8X8X8次遍历
枚举法可以进行优化,即若在放置第2,或3个棋子,即没有将棋子全部放入棋盘中时,进行判断,将不符合要求的情况直接排除,不再继续循环,这样能够大大减少循环次数,不必模拟所有棋子放置方式
优化方式:在main方法中做优化,增加判断语句
int main() { int index[8]; //多层循环,穷举每一种放置方式 for (index[0] = 1; index[0] <= 4; index[0]++) { for (index[1] = 1; index[1] <= 4; index[1]++) { //增加判断 if(Judge(index, 2)) for (index[2] = 1; index[2] <= 4; index[2]++) { //增加判断 if (Judge(index, 3)) for (index[3] = 1; index[3] <= 4; index[3]++) { //判断棋子放置是否合乎规则,正确则打印,不正确则继续 if (Judge(index, 4)) { Sloution(index); } else { continue; } } } } } cin.get(); return 0;}
方案2—-回溯法:
main函数:
int main() { int index[4] = { 0 }; int i = 0; while (i > -1) { index[i]++; while (index[i] < 6 && _judge(index, i)) { index[i]++; } if (index[i] <= 4) { if (i == 3) { //是四皇后的正确结果,调用函数打印正确答案 result(index); } else { i++; index[i] = 0; } } else { i--; } } cin.get(); return 0;}
_judge函数:
inline bool _judge(int *index, int num) { for (int i = 0; i < num; i++) { if (index[i] == index[num] || abs(index[i] - index[num]) == num - i) { return true; } } return false;}
result函数:
inline void result(int *index) { cout << "四皇后问题的一种正确解法,横坐标从0到4的4列上,纵坐标的值依次是:"; for (int i = 0; i < 4; i++) { cout << index[i]; } cout << endl;}
使用递归优化程序:
上述程序太难懂,可以使用递归优化上述程序,如下:
result函数和_judge函数不变
回调函数:
void callback(int *index,int i) { if (i > 3){ result(index); } else{ int j = 0; while (++j <= 4) { index[i] = j; if (_judge(index, i) == 0) { callback(index,i+1); } } }}
main函数:
int main() { int index[4] = { 0,0,0,0 }; int i = 0; callback(index,i); cin.get(); return 0;}
方案3—-回溯法结合递归和栈数据结构
在严蔚敏编著的C语言数据结构栈数据结构部分,书中提及使用栈解决四皇后问题
栈数据结构解决和回溯相关的问题时非常的方便易懂,下面介绍一下使用栈解决四皇后问题,这是本文最简单易懂的方法,但是需要实现编写栈数据结构,当然也可以使用STL中的栈
#include "assist.h"#include"Stack.h"#include<iostream>//创建一个全局栈Stack<int> stack(11);//回调函数void callback() { if (stack.getSize() == 3) { cout << "正确答案" << endl; stack.Print(); } else { int j = 0; while (++j <= 4) { //进栈 stack.Push(j); if (_judge( stack.getElements(), stack.getSize()) == 0) { //打印整个栈中的数据 stack.Print(); cout << stack.getSize() << endl; callback(); } //弹栈 stack.Pop(); } }}int main() { callback(); cin.get(); return 0;}
- 经典算法问题-01-八皇后
- 【经典算法】八皇后问题
- 经典算法之八皇后问题
- 经典算法问题——八皇后
- 【经典算法】八皇后问题C#版
- 经典回溯算法(八皇后问题)
- 八皇后问题(经典回溯算法)
- 经典算法之八皇后问题
- 八皇后问题(经典回溯算法)
- 经典八皇后问题;
- 经典八皇后问题
- 经典八皇后问题
- 八皇后问题[算法]
- 八皇后问题算法
- 算法问题-八皇后
- 算法--八皇后问题
- 算法-八皇后问题
- 算法八皇后问题
- C++11 std::bind std::function 高级用法
- SpringMVC(七)拦截器
- PAT (Advanced Level) Practise 1001. A+B Format (20)
- Android RecyclerView更新子项目notifyItemChanged
- c++学习日记/函数指针与指针函数
- 经典算法问题-01-八皇后
- SAP Fiori 最新视频教程--由浅入深学习Fiori开发
- C表达式((void (*)(void))0();
- 科学研究设计二:定量分析和定性分析
- 一位10年 Java 工作经验的架构师聊 Java 和工作经验
- A required library with BLAS API not found.
- 一万行注释之静态代理和动态代理
- 可靠性测试主要注意点
- 同时装了Python3和Python2,怎么用pip?