回溯法:

回溯的意义是在递归直到可解的最小问题后,逐步返回原问题的过程,而这里所说的回溯算法实际上是一个类似枚举的搜索尝试方法,它的主题思想是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。

回溯算法师尝试搜索算法中最基本的一种算法,其采用了一种“走不通就掉头”的思想,作为控制结构。在使用回溯算法解决问题中每向前走一步都有很多路径需要选择,但当没有决策信息或决策信息不充分时,只好尝试某一路径向下走,直至走到一定程度后得知此路不通时,再回溯到上一步尝试其他路径;当然在尝试成功时,则问题得解而算法结束。

回溯法典型例题-八皇后问题:

要在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. 算法分析与设计课程复习之回溯法

    算法分析与设计课程复习之回溯法 一.基本思想 1.解空间 设问题的解向量为X=(x1,x2,-,xn) ,xi的取值范围为有穷集Si .把xi的所有可能取值组合,称为问题的解空间.每一个组合是问题的一 ...

  2. 算法分析与设计——八皇后问题(回溯法)

    在国际象棋中,皇后是最厉害的棋子,可以横走.直走,还可以斜走.棋手马克斯·贝瑟尔 1848 年提出著名的八皇后问题:即在 8 × 8 的棋盘上摆放八个皇后,使其不能互相攻击 -- 即任意两个皇后都不能 ...

  3. 八皇后问题 回溯法hdu2553

    N皇后问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  4. n皇后问题-回溯法求解

    n皇后问题-回溯法求解 1.算法描述 在n×n格的国际象棋上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. n皇后是由八皇后问题演变而来的.该问题 ...

  5. Bailian2754 八皇后【回溯】

    2754:八皇后 总时间限制: 1000ms 内存限制: 65536kB 描述 会下国际象棋的人都很清楚:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * 8个方格) ...

  6. 算法设计与分析之回溯法

    文章目录 前言 一.回溯法概述 二.回溯法的基本思想 三.回溯法的设计步骤 四.回溯法效率分析 五.回溯法示例 总结 前言 大家好,越努力,越幸运,我是程序猿小猿.本篇文章小猿将跟您分享算法设计与分析 ...

  7. 八皇后问题、N皇后问题回溯法详解

    /* * 回溯法解N皇后问题 * 使用一个一维数组表示皇后的位置 * 其中数组的下标表示皇后所在的行 * 数组元素的值表示皇后所在的列 * 这样设计的棋盘,所有皇后必定不在同一行 * * 假设前n-1 ...

  8. Bailian2698 八皇后【回溯】

    2698:八皇后问题 总时间限制: 10000ms 内存限制: 65536kB 描述 在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方. 输入 无输入. 输出 按给定顺序和格式输出所有 ...

  9. 算法设计与分析复习--回溯法

    算法设计与分析期末复习 主要参考: ​ 算法设计与分析(北京航空航天大学MOOC) ​ 算法设计与分析(北京大学MOOC) ​ 华中科技大学 计算机科学与技术学院 算法设计与分析 课堂教学PPT 五. ...

最新文章

  1. smarty_modifier_truncate,无或者有md_substr的情况下都能正确截取字符串的php函数,可用于smarty。...
  2. 得到的概率值_论文推荐|屋面钢梁在超强意外雪荷载作用下的失效概率
  3. 网络开源框架之libevent使用实例
  4. 模拟器不全屏_刺激战场:腾讯模拟器怎么设置才不卡
  5. 前端学习(1035):bootstrap-js插件1
  6. mysql json 创建索引_MySQL · 最佳实践 · 如何索引JSON字段
  7. EIM正在迎来自己的春天
  8. android学习笔记---42_服务的生命周期
  9. 深入理解BGP的几个路由特性(试读连载六)
  10. ubuntu 18.04 增加新磁盘、挂载、格式化
  11. Android开发之自定义UI组件和属性
  12. VS2012使用 MSDN教程
  13. 基于MATLAB视频的人体姿态检测
  14. Kubuntu samba安装
  15. 为什么Excel公式使用不了?
  16. 【材料整理】 -- DTI相关知识点
  17. 我是学计算机的表情包,我是一个热爱学习的人表情包
  18. 基于Python的数字图形可视化水印系统的设计与实现
  19. spring cloud 资源服务器授权配置
  20. DEL命令居然无法删除文件夹!

热门文章

  1. facebook instant game 发布指南-设置智能助手
  2. 登录秒领2个月PPTV会员秒到 无需复杂步骤
  3. mac下打开隐藏文件夹的方法
  4. java metadata 使用_java 查询oracle数据库所有表DatabaseMetaData的用法(详解)
  5. pid温度控制c语言程序及仿真,温度控制PID算法的C语言程序实例代码
  6. 计算机二级vf vc,计算机二级VF:实战VC时间控制函数
  7. 服务器命令栏不显示,Linux栏 Linux指令(未完)
  8. 垓下古战场发现龙山文化时期城址
  9. 捣蛋phpwind之WindFrameWork
  10. farpoint使用