八皇后问题 :假设 將八个皇后放到国际象棋盘上,使其两两之间无法相互攻击。共有几种摆法?

基础知识:

国际象棋里,棋盘为8X8格。

皇后每步可以沿直线、斜线 走任意格。

思路:

1.想把8个皇后放进去,肯定最终每行只有一个皇后,每列只有一个皇后。

2.设个二维数组chess [ i ] [ j ] 模拟棋盘,cas存放摆法。i j 是表示i行j列:

写一个用于递归的函数,思路如下

3.从上往下一行行的放皇后,放下一行时从最左边(第0列)放起,如果不能放就往右挪一格再试。注意判断右边有没有越界出棋盘。

4.写一个函数专门判断当前位置能不能放,只需要判断该位置的横、竖、两对角线,这四条线上有没有其他皇后即可。命名为check。

5.如果把最后一行放完了,那就统计上这个摆法,cas++。摆完最后一行不能继续判断下一行了。

6.放完一种情况,还要探究其他情况,可以把现在放好的皇后“拿走”,然后再试探 之前没试探过的棋盘格。

7.拿走皇后操作可以和不能放皇后的操作用同样的代码实现:

如果这个位置不能放,要把它置零,表示没有皇后。

如果这位置能放,那就放皇后(置1)。等一种情况讨论完,还得把它拿开,“拿开”也是置零的操作。

所以应该想办法排列上述代码,保证已经把摆出的情况记录下来,之后执行“拿开皇后”代码。

下面是递归函数部分:

  1. void queen(int i,int j){
  2. if(j>=line){ //如果右侧越界
  3. return ;
  4. }
  5.  
  6. if(check(i,j)==1){//如果能放
  7. chess[i][j]=1;//放皇后
  8. if(i==line-1){//如果是最后一行,记录情况
  9. cas++;
  10. }
  11. else{
  12. queen(i+1,0);//不是最后一行就分析下一行
  13. }
  14. }
  15. 	//下面这两句是最精彩的
  16.  chess[i][j]=0;//如果此位置不能放,就置空(0),判断旁边的格子。
  17. //如果此位置能放,走到这里就意味着上面的代码全部执行了,把皇后拿走(置零),再讨论其他情况,拿旁边位置试探。

  18. queen(i,j+1);

  19. }

然后开始写判断函数check。需要判断的是8个方向,把它看成4条直线考虑。对于所在的横行,竖列,直接用for循环判断。接下来考虑对角线(红色)。

这样可以看出来,要判断的对角线是每个象限的平分线,每次 i ,j 的变化量是相等的,只是符号有差异。横纵坐标变化量的范围是-8~8,当对角线走到边框时停止判断。

为什么是-8到8呢?因为咱们没必要确定对角线的精确范围,上图是最理想的对角线,但是因为目标位置不同,对角线范围也不同,每次计算两端点是不可取的。

直接按最长对角线划:

核心代码:

  1. for(k=-line;k<=line;k++){//两对角线
  2. if(i+k>=0&&i+k<line&&j+k>=0&&j+k<line)//从左上到右下对角线,如果在棋盘格里
  3. if(chess[i+k][j+k]==1) return 0;
  4.  
  5. if(i-k>=0&&i-k<line&&j+k>=0&&j+k<line)//从左下到右上对角线,如果在棋盘格里
  6. if(chess[i-k][j+k]==1) return 0;
  7. }

这个判断函数不重要,你写的函数达到目的就行。

注意一点,此函数只能设计成判断功能,不可以改变棋盘格的填充。

我刚开始觉得,当放置完上一个皇后,直接把这皇后所在的横纵斜方向全部填充一个数字,列为‘‘禁地’’,下一皇后放置时只要看待放入位置是否是“禁地”即可。但这么做是错的,因为不是把棋盘格填好一次就ok了,摆好一次后还需要把最后放的棋子拿开,探讨其他情况。如果划分禁地后,拿走皇后还得把禁地复原了,很麻烦的说。。而且代码量也不节省,就这么判断就行。

代码块的思路讲完,下面是完整代码。运行结果:92.

你写的程序也要保证这个结果。

  1. #include<stdio.h>
  2. #define line 8
  3. void queen(int i,int j);
  4. int check(int i,int j);
  5. int chess[line][line];
  6. int cas=0;
    int xx,yy;

  7. int main(){
  8. queen(0,0);
  9. printf("%d\n",cas);
  10. return 0;
  11. }
  12.  
  13. void queen(int i,int j){
  14. if(j>=line){
  15. return ;
  16. }
  17.  
  18. if(check(i,j)==1){//如果能放
  19. chess[i][j]=1;//放皇后
  20. if(i==line-1){//如果是最后一行,记录情况
  21. cas++;
  22. /*下面是输出每种棋盘结果,供测试
  23.  
  24. for (xx=0;xx<8;xx++)
  25.  
  26. for(yy=0;yy<8;yy++){
  27.  
  28. printf("%d",chess[xx][yy]);
  29.  
  30. if(yy==7)
  31.  
  32. printf("\n");
  33.  
  34. }
  35.  
  36. printf("\n");
  37.  
  38. 上面是输出结果*/
  39.  
  40. }
  41. else{
  42. queen(i+1,0);//不是最后一行就分析下一行
  43. }
  44. }
  45. chess[i][j]=0;//如果此位置不能放,就置空(0),判断旁边的格子。
  46. //如果此位置能放,走到这里就意味着上面的代码全部执行了,把皇后拿走(置零),再讨论其他情况,拿旁边位置试探。
  47. queen(i,j+1);
  48. }
  49.  
  50.  
  51. int check(int i,int j){
  52. int k;
  53.  
  54. for(k=0;k<line;k++){
  55. if(chess[i][k]==1) return 0;//0=不能放
  56. }
  57. for(k=0;k<line;k++){
  58. if(chess[k][j]==1) return 0;
  59. }
  60. for(k=-line;k<=line;k++){//两对角线
  61. if(i+k>=0&&i+k<line&&j+k>=0&&j+k<line)//从左上到右下对角线
  62. if(chess[i+k][j+k]==1) return 0;
  63.  
  64. if(i-k>=0&&i-k<line&&j+k>=0&&j+k<line)//从左下到右上对角线
  65. if(chess[i-k][j+k]==1) return 0;
  66. }
  67. return 1;
  68. }

八皇后问题 递归实现 C语言 超详细 思路 基础的更多相关文章

  1. java实现八皇后问题(递归和循环两种方式)

    循环方式: package EightQueens;   public class EightQueensNotRecursive { private static final boolean AVA ...

  2. 八皇后非递归(仅使用一个数组且可扩展为N皇后问题)

    </pre><pre name="code" class="cpp">/* Theme:八皇后(非递归) Coder:秒针的声音 Tim ...

  3. 八皇后问题 --- 递归解法 --- java代码

    八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行.纵行或斜线上.八皇后 ...

  4. 零基础入门C语言超详细的字符串详解

    本篇文章是对C语言字符串操作进行了详细的总结分析,需要的朋友参考下 1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, ...

  5. 超详细“零”基础kafka入门篇

    1.认识kafka 1.1 kafka简介 Kafka 是一个分布式流媒体平台 kafka官网:http://kafka.apache.org/ (1)流媒体平台有三个关键功能: 发布和订阅记录流,类 ...

  6. (企业面试部分)超详细思路讲解SQL语句的查询实现,及数据的创建。

    企业面试部分详细的SQL问题,思路讲解 第一步:创建数据库表,及插入数据信息 --Student(S#,Sname,Sage,Ssex) 学生表 CREATE TABLE student( sno ) ...

  7. Swift超详细的基础语法-结构体,结构体构造器,定义成员方法, 值类型, 扩充函数

    知识点 基本概念 结构体的基本使用 结构体构造器(构造函数/构造方法) 结构体扩充函数(方法), 又称成员方法 结构体是值类型 1. 基本概念 1.1 概念介绍 结构体(struct)是由一系列具有相 ...

  8. 超详细思路讲解SQL语句的查询实现,及数据的创建。

    最近一直在看数据库方面的问题,总结了一下SQL语句,这是部分详细的SQL问题,思路讲解: 第一步:创建数据库表,及插入数据信息 --Student(S#,Sname,Sage,Ssex) 学生表 CR ...

  9. 超详细Java基础-多态

    茫茫人海千千万万,感谢这一秒你看到这里.希望我的能对你的有所帮助!共勉! 愿你在未来的日子,保持热爱,奔赴山海! Java基础知识(多态) 多态 多态就是指程序中定义的引用变量所指向的具体类型和通过该 ...

随机推荐

  1. JustOj 1974: 简单的事情 (组合数)

    题目描述 数学天才fans曾经说过一句话:组合数的计算是一件非常简单的事情.组合数的计算真的是一件非常简单的事情吗?请你自己去尝试一下吧! 输入 输入中的一些整数对n,m(m≤n≤20) 输出 输出其 ...

  2. oracel中合并报表的sql

    select decode(dt.LATN_ID ,290,'西安','910','咸阳',911,'延安',912,'榆林',913,'渭南',914,'商洛',915,'安康', 916,'汉中' ...

  3. JavaUtil smtp 邮件发送

    需要用到的jar包:javax.mail.jar package com.lee.util; import java.io.UnsupportedEncodingException; import j ...

  4. 同行span标签设置display:inline-block;overflow:hidden垂直对齐问题

    1 问题描述:一个div包含 三个span 当span2 类样式设置如下图时,将导致垂直方向不对齐的情况 2解决方案: 将前面的也设置同样的样式 overflow:hidden; display:in ...

  5. 深度估计&平面检测小结

    https://yq.aliyun.com/ziliao/582885 最近一段时间已知忙着赶图像分析与理解的项目,在三个星期内强行接触了CNN,MRF,Caffe,openCV在内的很多东西.现在项 ...

  6. 利用cookies跳过登陆验证码

    前言在爬取某些网页时,登陆界面时经常遇到的一个坎,而现在大多数的网站在登陆时都会要求用户填写验证码.当然,我们可以设计一套机器学习的算法去破解验证码,然而,验证码的形式多种多样,稍微变一下(有些甚至是 ...

  7. 【题解】Luogu SP8791 DYNALCA - Dynamic LCA

    原题传送门 这题用Link-Cut-Tree解决,Link-Cut-Tree详解 这道题的难点就在如何求LCA: 我们珂以先对其中一个点进行access操作,然后对另一个点进行access操作,因为L ...

  8. MS11-050安全漏洞

    IE浏览器渗透攻击--MS11050安全漏洞 实验前准备 1.两台虚拟机,其中一台为kali,一台为windows xp sp3(包含IE7). 2.设置虚拟机网络为NAT模式,保证两台虚拟机可以相互 ...

  9. Office 2016 永久激活

    启示:office突然过期,QWQ,卖电脑的真坑爹,找了好多办法,总结2个不花钱的办法啦. 1>只有30天试用期 Office 2016预览版序列号:NKGG6-WBPCC-HXWMY-6DQG ...

  10. NOIP 车站分级 (luogu 1983 & codevs 3294 & vijos 1851) - 拓扑排序 - bitset

    描述 一条单向的铁路线上,依次有编号为 1, 2, ..., n 的 n 个火车站.每个火车站都有一个级别,最低为 1 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车 ...