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

基础知识:

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

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

思路:

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

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

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

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

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

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

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

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

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

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

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

下面是递归函数部分:

void queen(int i,int j){
if(j>=line){ //如果右侧越界
return ;
} if(check(i,j)==1){//如果能放
chess[i][j]=1;//放皇后
if(i==line-1){//如果是最后一行,记录情况
cas++;
}
else{
queen(i+1,0);//不是最后一行就分析下一行
}
}
	//下面这两句是最精彩的
 chess[i][j]=0;//如果此位置不能放,就置空(0),判断旁边的格子。

//如果此位置能放,走到这里就意味着上面的代码全部执行了,把皇后拿走(置零),再讨论其他情况,拿旁边位置试探。
queen(i,j+1);
}

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

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

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

直接按最长对角线划:

核心代码:

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

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

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

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

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

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

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

int main(){
queen(0,0);
printf("%d\n",cas);
return 0;
} void queen(int i,int j){
if(j>=line){
return ;
} if(check(i,j)==1){//如果能放
chess[i][j]=1;//放皇后
if(i==line-1){//如果是最后一行,记录情况
cas++;
/*下面是输出每种棋盘结果,供测试
for (xx=0;xx<8;xx++) for(yy=0;yy<8;yy++){ printf("%d",chess[xx][yy]); if(yy==7) printf("\n"); } printf("\n"); 上面是输出结果*/ }
else{
queen(i+1,0);//不是最后一行就分析下一行
}
}
chess[i][j]=0;//如果此位置不能放,就置空(0),判断旁边的格子。
//如果此位置能放,走到这里就意味着上面的代码全部执行了,把皇后拿走(置零),再讨论其他情况,拿旁边位置试探。
queen(i,j+1);
} int check(int i,int j){
int k; for(k=0;k<line;k++){
if(chess[i][k]==1) return 0;//0=不能放
}
for(k=0;k<line;k++){
if(chess[k][j]==1) return 0;
}
for(k=-line;k<=line;k++){//两对角线
if(i+k>=0&&i+k<line&&j+k>=0&&j+k<line)//从左上到右下对角线
if(chess[i+k][j+k]==1) return 0; if(i-k>=0&&i-k<line&&j+k>=0&&j+k<line)//从左下到右上对角线
if(chess[i-k][j+k]==1) return 0;
}
return 1;
}

八皇后问题 递归实现 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. hibernate二级缓存ehcache hibernate配置详解

    <!-----------------hibernate二级缓存ehcache------------------------->hibernate配置 <prop key=&quo ...

  2. redis安装集群的2种方式

    redis主从只是数据的备份,当主宕机后不会自动切换从为主,需要手动切换从为主. 哨兵就可以自动切换从为主, 当主数据库遇到异常中断服务后,开发者可以通过手动的方式选择一个从数据库来升格为主数据库,以 ...

  3. The Little Prince-12/06

    The Little Prince-12/06 “That doesn't matter. Draw me a sheep.” When the prince ask the planet to dr ...

  4. Camera2点击对焦实现2

    https://www.aliyun.com/jiaocheng/22218.html 阿里云 >  教程中心   >  android教程 >  Camera2点击对焦实现 Cam ...

  5. Docker学习笔记之镜像与容器

    0x00 概述 镜像和容器作为 Docker 里最基础的概念,我们很有必要了解 Docker 对它们的很多定义以及其他与它们有关的知识.在这一小节里,我们就专门针对镜像与容器两个概念展开,细致的梳理与 ...

  6. js条件判断if-else和switch、循环for和while

    条件判断和循环都使用{ }将代码块括起来,如果代码块只有一行,则可省略{ }. 在循环中,continue表示跳过当前循环继续进行下一次循环,break表示跳出整个循环. 1.条件判断if-else, ...

  7. P1357 花园

    洛咕原题 题解 状压dp+矩乘 首先看到题目说M<=5,这么小的数据明显可以用状压保存相邻状态,于是可以得到一个80分的dp: 先筛出所有可用的状态,然后建立一个矩阵保存可转移的状态,再然后把每 ...

  8. VScode 好用插件集合(一)

    VScode 好用插件集合(一) 什么是VScode Visual Studio Code (简称 VS Code / VSC) 是一款免费开源的现代化轻量级代码编辑器,支持几乎所有主流的开发语言的语 ...

  9. Redis热点Key发现及常见解决方案!

    一.热点Key问题产生的原因 1.用户消费的数据远大于生产的数据(热卖商品.热点新闻.热点评论.明星直播). 在日常工作生活中一些突发的的事件,例如:双十一期间某些热门商品的降价促销,当这其中的某一件 ...

  10. Java并发编程73道面试题及答案 —— 面试稳了

    今天主要整理一下 Java 并发编程在面试中的常见问题,希望对需要的读者有用. 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任 ...