算法分析与设计-八皇后问题(回溯法)
回溯法:
回溯的意义是在递归直到可解的最小问题后,逐步返回原问题的过程,而这里所说的回溯算法实际上是一个类似枚举的搜索尝试方法,它的主题思想是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。
回溯算法师尝试搜索算法中最基本的一种算法,其采用了一种“走不通就掉头”的思想,作为控制结构。在使用回溯算法解决问题中每向前走一步都有很多路径需要选择,但当没有决策信息或决策信息不充分时,只好尝试某一路径向下走,直至走到一定程度后得知此路不通时,再回溯到上一步尝试其他路径;当然在尝试成功时,则问题得解而算法结束。
回溯法典型例题-八皇后问题:
要在8*8的国际象棋棋盘中放八个皇后,使任意两个皇后都不能互相吃掉。规则:皇后能吃掉同一行、同一列、同一对角线的任意棋子。下图为一种方案,求所有的解。
第一种解决方法就是枚举法,这种方法较为简单,共有8^8个状态,但实际搜索当中并不会搜索那么多种状态,因为前面已经说明,回溯法采用的是“走不通就掉头”的策略,所以当我们枚举时候加一些相应的约束条件,可使算法的效率大大提高。
那么怎么确定约束条件呢?
约束条件有三个:
(1)不在同一列,即:xi !=xj(xi ,xj 分别代表第 i ,j 个皇后分别位于第 xi , xj 列);
(2)不在同一主对角线:xi - i != xj - j;
(3)不在同一副对角线:xi + i ! = xj + j;
(2)和(3)又可以合并为一个“不在同一对角线上”的约束条件,表示为:
abs( xi - xj ) != abs( i - j ) abs()代表取绝对值。
故得到算法如下
算法一:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int check(int a[ ],int n)
{int i;for(i=1; i<=n-1; i++)if(abs(a[i]-a[n])==abs(i-n)||(a[i]==a[n]))return 0;return 1;
}
int main()
{int a[9];for(a[1]=1; a[1]<=8; a[1]++){for(a[2]=1; a[2]<=8; a[2]++){if(check(a,2)==0)continue;for(a[3]=1; a[3]<=8; a[3]++){if(check(a,3)==0)continue;for(a[4]=1; a[4]<=8; a[4]++){if(check(a,4)==0)continue;for(a[5]=1; a[5]<=8; a[5]++){if(check(a,5)==0)continue;for(a[6]=1; a[6]<=8; a[6]++){if(check(a,6)==0)continue;for(a[7]=1; a[7]<=8; a[7]++){if(check(a,7)==0)continue;for(a[8]=1; a[8]<=8; a[8]++){if(check(a,8)==0)continue;else{for(int i=1; i<=8; i++)printf("%d ",a[i]);printf("\n");}}}}}}}}}
}
枚举算法虽然有很好的可读性,也能从中体会到回溯的思想,但它只能解决“皇后个数为常量”的问题,却不能解决任意的n皇后问题,下面就是典型的非递归回溯算法:
算法二:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int a[30],n;
bool check(int k)
{for(int i=1; i<k; i++)if(abs(a[i]-a[k])==abs(i-k)||a[i]==a[k])return false;return true;
}
void output()
{for(int i=1; i<=n; i++)cout<<a[i]<<" ";cout<<endl;
}
void backdate(int n)
{int k=1;a[1]=0;while(k>0){a[k]++;while(a[k]<=n&&check(k)==false) //为第k个皇后搜索位置a[k]++;if(a[k]<=n){if(k==n) //找到一组解output();elsea[++k]=0;//下一个皇后要从头开始搜索}elsek--;//回溯}
}
int main()
{cin>>n;backdate(n);
}
递归回溯算法:
我们用b,d,c数组分别来记录棋盘上的n个列,2n-1个主对角线,2n-1个副对角线的占用情况。
说明:
用i,j分别 表示皇后所在的行列(或者说i号皇后在j列),同一主对角线上的行列下标的差一样,若用表达式 i-j 编号,则范围是 -n+1 ~ n+1,所以用i-j+n表示主对角线编号,范围就是1~ 2n-1。同样地,副对角线上行列下标的和一样,用表达式i+j编号,则范围2~2n。
算法三:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int a[20],b[20],c[20],d[20];
int n,t,k;
void output()
{t++;cout<<t<<":";for(int k=1;k<=n;k++)cout<<" "<<a[k];cout<<endl;
}
void tryy(int i)
{for(int j=1;j<=n;j++){if(b[j]==0&&c[i+j]==0&&d[i-j+n]==0){a[i]=j; //摆放皇后b[j]=1; //占领第j列c[i+j]=1; //主对角线d[i-j+n]=1; //副对角线if(i<n)tryy(i+1); //搜索else //找到一组解output();b[j]=0;c[i+j]=0;d[i-j+n]=0; //重新设置为0}}
}int main()
{cin>>n;for(int i=1;i<=n;i++){b[i]=0;c[i]=0;c[n+i]=0;d[i]=0;}tryy(1);
}
算法分析与设计-八皇后问题(回溯法)相关推荐
- 算法分析与设计课程复习之回溯法
算法分析与设计课程复习之回溯法 一.基本思想 1.解空间 设问题的解向量为X=(x1,x2,-,xn) ,xi的取值范围为有穷集Si .把xi的所有可能取值组合,称为问题的解空间.每一个组合是问题的一 ...
- 算法分析与设计——八皇后问题(回溯法)
在国际象棋中,皇后是最厉害的棋子,可以横走.直走,还可以斜走.棋手马克斯·贝瑟尔 1848 年提出著名的八皇后问题:即在 8 × 8 的棋盘上摆放八个皇后,使其不能互相攻击 -- 即任意两个皇后都不能 ...
- 八皇后问题 回溯法hdu2553
N皇后问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
- n皇后问题-回溯法求解
n皇后问题-回溯法求解 1.算法描述 在n×n格的国际象棋上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. n皇后是由八皇后问题演变而来的.该问题 ...
- Bailian2754 八皇后【回溯】
2754:八皇后 总时间限制: 1000ms 内存限制: 65536kB 描述 会下国际象棋的人都很清楚:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * 8个方格) ...
- 算法设计与分析之回溯法
文章目录 前言 一.回溯法概述 二.回溯法的基本思想 三.回溯法的设计步骤 四.回溯法效率分析 五.回溯法示例 总结 前言 大家好,越努力,越幸运,我是程序猿小猿.本篇文章小猿将跟您分享算法设计与分析 ...
- 八皇后问题、N皇后问题回溯法详解
/* * 回溯法解N皇后问题 * 使用一个一维数组表示皇后的位置 * 其中数组的下标表示皇后所在的行 * 数组元素的值表示皇后所在的列 * 这样设计的棋盘,所有皇后必定不在同一行 * * 假设前n-1 ...
- Bailian2698 八皇后【回溯】
2698:八皇后问题 总时间限制: 10000ms 内存限制: 65536kB 描述 在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方. 输入 无输入. 输出 按给定顺序和格式输出所有 ...
- 算法设计与分析复习--回溯法
算法设计与分析期末复习 主要参考: 算法设计与分析(北京航空航天大学MOOC) 算法设计与分析(北京大学MOOC) 华中科技大学 计算机科学与技术学院 算法设计与分析 课堂教学PPT 五. ...
最新文章
- smarty_modifier_truncate,无或者有md_substr的情况下都能正确截取字符串的php函数,可用于smarty。...
- 得到的概率值_论文推荐|屋面钢梁在超强意外雪荷载作用下的失效概率
- 网络开源框架之libevent使用实例
- 模拟器不全屏_刺激战场:腾讯模拟器怎么设置才不卡
- 前端学习(1035):bootstrap-js插件1
- mysql json 创建索引_MySQL · 最佳实践 · 如何索引JSON字段
- EIM正在迎来自己的春天
- android学习笔记---42_服务的生命周期
- 深入理解BGP的几个路由特性(试读连载六)
- ubuntu 18.04 增加新磁盘、挂载、格式化
- Android开发之自定义UI组件和属性
- VS2012使用 MSDN教程
- 基于MATLAB视频的人体姿态检测
- Kubuntu samba安装
- 为什么Excel公式使用不了?
- 【材料整理】 -- DTI相关知识点
- 我是学计算机的表情包,我是一个热爱学习的人表情包
- 基于Python的数字图形可视化水印系统的设计与实现
- spring cloud 资源服务器授权配置
- DEL命令居然无法删除文件夹!
热门文章
- facebook instant game 发布指南-设置智能助手
- 登录秒领2个月PPTV会员秒到 无需复杂步骤
- mac下打开隐藏文件夹的方法
- java metadata 使用_java 查询oracle数据库所有表DatabaseMetaData的用法(详解)
- pid温度控制c语言程序及仿真,温度控制PID算法的C语言程序实例代码
- 计算机二级vf vc,计算机二级VF:实战VC时间控制函数
- 服务器命令栏不显示,Linux栏 Linux指令(未完)
- 垓下古战场发现龙山文化时期城址
- 捣蛋phpwind之WindFrameWork
- farpoint使用