八皇后c语言代码

合集下载

八皇后问题

八皇后问题

计算机科学与技术专业数据结构课程设计报告设计题目:八皇后问题目录1需求分析 (2)1.1功能分析 (2)1.2设计平台 (3)2概要设计 (3)2.1算法描述 (4)2.2算法思想 (5)2.3数据类型的定义 (5)3详细设计和实现 (6)3.1算法流程图 (6)3.2 主程序 (6)3.3 回溯算法程序 (7)4调试与操作说明 (9)4.1调试情况 (9)4.2操作说明 (9)5设计总结 (11)参考文献 (12)附录 (12)1需求分析1.1功能分析八皇后问题是一个古老而著名的问题,该问题是十九世纪著名的数学家高斯1850年提出的,并作了部分解答。

高斯在棋盘上放下了八个互不攻击的皇后,他还认为可能有76种不同的放法,这就是有名的“八皇后”问题。

在国际象棋中,皇后是最有权利的一个棋子;只要别的棋子在它的同一行或同一列或同一斜线(正斜线或反斜线)上时,它就能把对方棋子吃掉。

所以高斯提出了一个问题:在8*8的格的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后都不能处于同一列、同一行、或同一条斜线上面,问共有多少种解法。

现在我们已经知道八皇后问题有92个解答。

1、本演示程序中,利用选择进行。

程序运行后,首先要求用户选择模式,然后进入模式。

皇后个数设0<n<11。

选择皇后个数后,进入子菜单,菜单中有两个模式可以选择。

2、演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中规定的运算命令:相应的输入数据和运算结果显示在其后。

3、程序执行的命令包括:1)进入主菜单。

2)选择皇后问题,输入是几皇后。

3)进入子菜单。

4)选择皇后显示模式。

5)选择结束4、测试数据1)N的输入为4;2)共有2个解答。

3)分别是○●○○○○●○○○○●●○○○●○○○○○○●○○●○○●○○1.2设计平台Windows2000以上操作系统;Microsoft Visual C++ 6.02概要设计问题:N后问题问题描述:国际象棋中皇后可以攻击所在行,列,斜线上的每一个位置,按照此规则要在一个n*n的棋盘上放n个皇后使每一个皇后都不互相攻击问题分析:引入1个数组模拟棋盘上皇后的位置引入3个工作数组行数组[k]=1,表示第k行没有皇后右高左低数组[k]=1,表示第k条右高左低的斜线上没有皇后左高右低数组[k]=1,表示第k条左高右低的斜线上没有皇后观察棋盘找到规律同一右高左低的斜线上的方格,它们的行号和列号之和相等;同一左高右低的斜线上的方格,它们的行号和列号只差相等;开始时,所有行和斜线上都没有皇后,从第一列的第一行配置第一个皇后开始,在第m列的皇后位置数组[m]行放置了一个合理的皇后之后,准备考察第m+1列时,在数组行数组[],右高左低数组[],左高右低数组[]中为第m列,皇后位置数组[m]的位置设定有皇后标志如果按此放置位置得不到结果,则把当前列中的有皇后标记改为无皇后标记。

c语言回溯法

c语言回溯法

c语言回溯法回溯法是一种通过探索所有可能的候选解来找出所有解的算法。

如果候选解被确认不是一个解(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化来丢弃该解,即“回溯”并尝试另一个可能解。

这个过程一直进行到找到所有解或确定无解为止。

In computer science, the backtracking algorithm is a general, goal-oriented algorithm that explores all potential candidates for a solution by building candidates from a set of building blocks and eliminating those that fail to satisfy the constraints of the problem at some point. If a candidate solution is determined not to be a solution (or at least not the last solution), the backtracking algorithm backtracks, i.e., undoes the last step, to try another possibility. This process continues until a solution is found or until it is determined that no solution exists.在C语言中,实现回溯法通常涉及递归调用以及状态空间的维护。

递归调用用于在树的深度上进行探索,而状态空间(如数组、结构体等)用于记录当前的解构建状态。

以求解八皇后问题为例,这是一个经典的回溯法应用。

八皇后问题是在8x8的棋盘上放置八个皇后,使得任何一个皇后都不能攻击到其他皇后,即任意两个皇后都不能处于同一行、同一列或同一斜线上。

八皇后源代码及流程图

八皇后源代码及流程图

目录一需求分析 (1)1.1程序的功能: (1)1.2程序的输入输出要求: (1)二概要设计 (3)2.1程序的主要模块: (3)2.2程序涉及: (3)三详细设计 (3)3.1相关代码及算法 (4)3.1.1 定义相关的数据类型如下:....................... 错误!未定义书签。

3.1.2 主模块类C码算法: (4)3.1.3 画棋盘模块类C码算法 (5)3.1.4 画皇后模块类C码算法: (5)3.1.5 八皇后摆法模块(递归法): (6)3.1.6 初始化模块 (7)3.1.7 输出摆放好的八皇后图形(动态演示): (7)3.2相关流程图 (9)四调试分析 (12)五设计体会 (13)六附录 (13)七参考文献 (17)一需求分析1.1 程序功能:八皇后问题是一个古老而著名的问题。

该问题是十九世纪著名的数学家高斯1850年提出的。

八皇后问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子,问有多少种不同的摆法?并找出所有的摆法。

因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。

本程序通过对子函数void qu(int i)的调用,将八皇后的问题关键通过数据结构的思想予以了实现。

虽然题目以及演算看起来都比较复杂,繁琐,但在实际中,只要当一只皇后放入棋盘后,在横与列、斜线上没有另外一只皇后与其冲突,再对皇后的定位进行相关的判断。

即可完成。

如果在这个程序中,我们运用的是非递归的思想,那么将大量使用if等语句,并通过不断的判断,去推出答案,而且这种非递归的思想,大大的增加了程序的时间复杂度。

如果我们使用了数据结构中的算法后,那么程序的时间复杂度,以及相关的代码简化都能取得不错的改进。

这个程序,我运用到了数据结构中的栈、数组,以及树和回溯的方法。

八皇后问题代码实现

八皇后问题代码实现

八皇后问题代码实现/*代码解析*//* Code by Slyar */ #include &lt;stdio.h&gt;#include&lt;stdlib.h&gt; #define max 8 int queen[max], sum=0; /* max为棋盘最大坐标*/ void show() /* 输出所有皇后的坐标*/{ int i; for(i = 0; i &lt; max; i++){ printf("(%d,%d) ", i, queen[i]); }printf("\n"); sum++;} int check(int n) /* 检查当前列能否放置皇后*/{ int i; for(i = 0; i &lt; n; i++) /* 检查横排和对角线上是否可以放置皇后*/ { /* ///题目的要求是所有皇后不在同一横排、竖排、对角线上。

1、queen[n]值为竖排号,可看为Y轴上值。

n值为横排号,可看为X轴上值。

2、(1)先从横坐标第n点排开始放皇后,再放第n+1,所有不会同一横坐标点即同一竖排。

(2)queen[i] == queen[n]时即y坐标相等,即在同一横排,此时判断不合规则点。

(3)abs(queen[i] - queen[n]) == (n - i),可变形为(queen[n] - queen[i]) /(n - i)==tan45°或tan135° 由公式可得出,点(n,queen[n])与点(i,quuen[i])在同一条左斜线135°或右斜45°,即国际象棋上的每个格子的两条斜角线。

3、由2即可得出当前格式是否能放置一个皇后。

*/ if(queen[i] == queen[n] || abs(queen[i] - queen[n]) == (n - i)) { return1; } } return 0;} void put(int n) /* 回溯尝试皇后位置,n为横坐标*/{ int i; for(i = 0; i &lt; max;i++) { queen[n] = i; /* 将皇后摆到当前循环到的位置*/ if(!check(n)){ if(n == max - 1){ show(); /* 如果全部摆好,则输出所有皇后的坐标*/ } else { put(n + 1); /* 否则继续摆放下一个皇后*/ } } }} int main(){ put(0); /*从横坐标为0开始依次尝试*/ printf("TTTTTT----%d\n", sum); //system("pause"); //while(1); return 0;}/*算法系列---回溯算法引言寻找问题的解的一种可靠的方法是首先列出所有候选解,然后依次检查每一个,在检查完所有或部分候选解后,即可找到所需要的解。

C++课程设计八皇后问题

C++课程设计八皇后问题

安徽建筑工业学院数据结构设计报告书院系数理系专业信息与计算科学班级11信息专升本学号11207210138姓名李晓光题目八皇后指导教师王鑫1.程序功能介绍答:这个程序是用于解决八皇后问题的。

八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。

做这个课题,重要的就是先搞清楚哪个位置是合法的放皇后的位置,哪个不能,要先判断,后放置。

我的程序进入时会让使用者选择程序的功能,选【1】将会通过使用者自己手动输入第一个皇后的坐标后获得答案;选【2】将会让程序自动运算出固定每一个皇后后所有的排列结果。

2.课程设计要求答:(1)增加函数,完成每输入一组解,暂停屏幕,显示“按任意键继续!”。

(2)完善程序,编程计算八皇后问题共有集中排列方案。

(3)增加输入,显示在第一个皇后确定后,共有几组排列。

(4)将每组解的期盼横向排列输出在屏幕上,将五个棋盘并排排列,即一次8行同时输出5个棋盘,同样完成一组解后屏幕暂停,按任意键继续。

(5)求出在什么位置固定一个皇后后,解的数量最多,在什么位置固定皇后后,解的数量最少,最多的解是多少,最少的解是多少,并将最多,最少解的皇后位置及所有的解求出,同样5个一组显示。

3.对课程题目的分析与注释答:众所周知的八皇后问题是一个非常古老的问题,问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击。

按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子。

因此,本课程设计的目的也是通过用C++语言平台在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现。

使用递归方法最终将其问题变得一目了然,更加易懂。

首先要用到类,将程序合理化:我编辑了一个盘棋8*8的类:class Board,还有个回溯法的类:class Stack,关键的类好了,然后编辑好类的成员,然后编辑主函数利用好这些类的成员,让其运算出结果。

数据结构实验报告八皇后问题

数据结构实验报告八皇后问题

2007级数据结构实验报告实验名称:实验二——栈和队列学生姓名:班级:班内序号:学号:日期:2008年11月18日1.实验要求通过选择下面五个题目之一进行实现,掌握如下内容:➢进一步掌握指针、模板类、异常处理的使用➢掌握栈的操作的实现方法➢掌握队列的操作的实现方法➢学习使用栈解决实际问题的能力➢学习使用队列解决实际问题的能力利用栈结构实现八皇后问题。

八皇后问题19世纪著名的数学家高斯于1850年提出的。

他的问题是:在8*8的棋盘上放置8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列、同一斜线上。

请设计算法打印所有可能的摆放方法。

提示:1、可以使用递归或非递归两种方法实现2、实现一个关键算法:判断任意两个皇后是否在同一行、同一列和同一斜线上2. 程序分析2.1 存储结构采用栈存储,其结构图如下:2.2 关键算法分析函数原型: bool check(int i);2.2.1.1.1自然语言:检测至第i行所摆放的第i个皇后是否和之前的i-1个皇后发生冲突。

如是,则返回0;反之,则当前布局合法,返回1。

判断两个皇后是否相互攻击的准则是:若两个皇后处于同一行,或处于同一列,或处于同一斜线,就能相互攻击。

基于如上准则,函数check( )的工作原理是:考虑到数组的每个元素分别代表不同行的皇后,即每行只放置了一个皇后,所以不必考虑“同处一行相互攻击”的情形;对于同处一列,则语句:if(queen[s]==queen[t])就能判断出不同行的两个棋子是否同处一列;对于处于同一斜线的这种情况,首先,我们看出国际象棋的棋盘是一个八行八列的正方形。

因此我们可将棋盘想象为数学上的笛卡尔平面坐标系,两颗棋子想象为平面上的两个点,就很容易发现,为保证两颗棋子不处于同一斜线,只要过这两个点的直线斜率不为1或-1,就能达到要求。

由此可使用下列语句:if( abs(t-s) == abs(queen[s]-queen[t]) )其中t和s分别代表不同行的两个皇后,即数组queen[8]里不同下标的两个元素。

2011年计算机二级C语言编写程序题及答案解析精选1

2011年计算机二级C语言编写程序题及答案解析精选1

2011年计算机二级C语言编写程序题及答案解析精选【4.1】已知银行整存整取存款不同期限的月息利率分别为:0.315%期限一年0.330%期限二年月息利率=0.345%期限三年0.375%期限五年0.420%期限八年要求输入存钱的本金和期限,求到期时能从银行得到的利息与本金的合计。

【4.2】输入年份year和月month,求该月有多少天。

判断是否为闰年,可用如下C语言表达式:year%4==0&&year0!=0||year@0==0。

若表达式成立(即表达式值为1),则year 为闰年;否则,表达式不成立(即值为0),year为平年。

【4.3】编写一个简单计算器程序,输入格式为:data1op data2。

其中data1和data2是参加运算的两个数,op为运算符,它的取值只能是+、-、*、/。

【4.4】输入n值,输出如图所示矩形。

【4.5】输入n值,输出如图所示平行四边形。

【4.6】输入n值,输出如图所示高为n的等腰三角形。

【4.7】输入n值,输出如图所示高为n的等腰三角形。

【4.8】输入n值,输出如图所示高和上底均为n的等腰梯形。

【4.9】输入n值,输出如图所示高和上底均为n的等腰空心梯形。

【4.10】输入n值,输出如图所示边长为n的空心正六边型。

【4.11】输入n值,输出如图所示图形。

【4.12】输入n值,输出如图所示图形。

【4.13】输入n值,输出如图所示图形。

【4.14】输入n值,输出如图所示图形。

【4.15】输入n值,输出如图所示图形。

【4.16】输入n值,输出如图所示图形。

(例为n=6时)【4.17】编写程序,输出如图所示sin(x)函数0到2π的图形。

【4.18】编写程序,在屏幕上输出一个由*号围成的空心圆。

【4.19】编写程序,在屏幕上绘制如图余弦曲线和直线。

若屏幕的横向为x轴,纵向为y 轴,在屏幕上显示0~360度的cos(x)曲线与直线x=f(y)=45*(y-1)+31的迭加图形。

八皇后问题实验报告

八皇后问题实验报告

软件工程上机报告实验名称:八皇后问题图形界面求解姓名:郭恂学号:2011011435班级:11级数学班中国石油大学(北京)计算机科学与技术系一、试验程序截图:点击显示下一组解即可显示下一组解:同样的,如果点击上一组解即可显示上一组解。

若在第1组解时点击显示上一组解会弹出报错提示框。

同样,若在第92组解点击显示下一组解也会弹出报错提示框:二、程序代码程序使用Java语言编写,编写环境为jdk1.6.0_18。

使用编程开发环境eclipse.exe编写。

本程序创建了两个类,两个类在同一个工程中。

其中Queen类的作用仅仅用来保存八皇后问题计算结果的数据,便于画图时使用。

本程序大概由两部分组成,第一部分是解八皇后问题,第二部分是画图。

程序源代码为:类1:public class Queen{public int[] x=new int[8];public int[] y=new int[8];public String name;}类2:import javax.swing.*;import java.awt.event.*;import java.awt.*;import javax.swing.JOptionPane;public class bahuanghou extends JFrame implements ActionListener {//JLabel[] l;int number=0; //当前显示的解的编号int sum=0; //所有解得数量JLabel l2;JButton b1,b2; //b1为显示下一组解得按钮,b2为显示上一组解得按钮。

Queen[] q=new Queen[128]; //得到的解储存在Queen类的数组里面。

private Image bomb1=Toolkit.getDefaultToolkit().getImage("D:\\qizi1.JPG"); //黑格棋子为bomb1private Image bomb2=Toolkit.getDefaultToolkit().getImage("D:\\qizi2.JPG"); //白格棋子为bomb2public bahuanghou() //构造方法,初始化窗口。

八皇后问题 C++程序

八皇后问题 C++程序

八皇后问题下面本人所用的就是回溯的思想来解决八皇后问题的。

8行8列的棋盘上放八个皇后,且不相互攻击,即每一列每一行只能放一个皇后,且必须要放一个皇后。

采用循环回溯的方法,现在第一列放一个皇后,然后再在第二列放一个皇后,以此类推,直到八个皇后都放完为止。

每个for循环语句都有一条continue语句,用来继续跳出本次循环。

// Queen.cpp(main)#include <iostream>using std::cout;using std::endl;#include <iomanip>using std::setw;#include <cmath>// using std::abs;int main(){static int queen[9];static int count=1;for (int A=1;A<=8;A++){for (int B=1;B<=8;B++){if (B==A){continue;}queen[2]=B;if ((abs(B-A))==1){continue;}queen[1]=A;for (int C=1;C<=8;C++){if ((C==B) || (C==A)){continue;}if ((abs(C-B)==1)||(abs(C-A)==2)) {continue;}queen[3]=C;for (int D=1;D<=8;D++){if ((D==C)||(D==B)||(D==A)){continue;}if ((abs(D-C)==1)||(abs(D-B)==2)||(abs(D-A)==3)){continue;}queen[4]=D;for (int E=1;E<=8;E++){if ((E==D)||(E==C)||(E==B)||(E==A)){continue;}if((abs(E-D)==1)||(abs(E-C)==2)||(abs(E-B)==3)||(abs(E-A)==4)){continue;}queen[5]=E;for (int F=1;F<=8;F++){if ((F==E)||(F==D)||(F==C)||(F==B)||(F==A)){continue;}if((abs(F-E)==1)||(abs(F-D)==2)||(abs(F-C)==3)||(abs(F-B)==4)||(abs(F-A)==5)){continue;}queen[6]=F;for (int G=1;G<=8;G++){if((G==F)||(G==E)||(G==D)||(G==C)||(G==B)||(G==A)){continue;}if((abs(G-F)==1)||(abs(G-E)==2)||(abs(G-D)==3)||(abs(G-C)==4)||(abs(G-B)==5)||(abs(G-A)==6)){continue;}queen[7]=G;for (int I=1;I<=8;I++){if((I==G)||(I==F)||(I==E)||(I==D)||(I==C)||(I==B)||(I==A)){continue;}if((abs(I-G)==1)||(abs(I-F)==2)||(abs(I-E)==3)||(abs(I-D)==4)||(abs(I-C)==5)||(abs(I-B)==6)||(abs(I-A)==7)){continue;}queen[8]=I;cout<<" NO."<<setw(2)<<count<<": ";for (int i=1;i<=8;i++){cout<<setw(3)<<queen[i];}count++;cout<<endl;}}}}}}}}return 0;}运行结果如下:。

C语言回溯法解八皇后问题(八皇后算法)

C语言回溯法解八皇后问题(八皇后算法)

C语⾔回溯法解⼋皇后问题(⼋皇后算法)⼋皇后问题(N皇后问题)的回溯法求解⼀、问题描述在⼀个国际象棋棋盘上放置⼋个皇后,使得任何两个皇后之间不相互攻击,求出所有的布棋⽅法,并推⼴到N皇后情况。

⼆、参考资料啥⽂字都不⽤看,B站上有个⾮常详细的动画视频解说,上链接三、源代码#include<iostream>#include<vector>#include<string>using namespace std;void put_queen(int x, int y, vector<vector<int>>&attack){//实现在(x,y)放置皇后,对attack数组更新,xy表⽰放置皇后的坐标,attack表⽰是否可以放置皇后//⽅向数组,⽅便后⾯对8个⽅向进⾏标记static const int dx[] = { -1,-1,-1,0,0,1,1,1 };static const int dy[] = { -1,0,1,-1,1,-1,0,1 };attack[x][y] = 1;//将皇后位置标记为1//通过两层for循环,将该皇后可能攻击到的位置标记for (int i = 1; i < attack.size(); i++)//从皇后位置向1到n-1个距离延伸{for (int j = 0; j < 8; j++)//遍历8个⽅向{int nx = x + i * dx[j];//⽣成的新位置⾏int ny = y + i * dy[j];//⽣成的新位置列//在棋盘范围内if (nx >= 0 && nx < attack.size() && ny >= 0 && ny < attack.size())attack[nx][ny] = 1;//标记为1}}}//回溯算法//k表⽰当前处理的⾏//n表⽰n皇后问题//queen存储皇后的位置//attack标记皇后的攻击范围//solve存储N皇后的全部解法void backtrack(int k, int n, vector<string>& queen,vector<vector<int>>& attack,vector<vector<string>>& solve){if (k == n)//找到⼀组解{solve.push_back(queen);//将结果queen存储⾄solvereturn;}//遍历0⾄n-1列,在循环中,回溯试探皇后可放置的位置for (int i = 0; i < n; i++){if (attack[k][i] == 0)//判断当前k⾏第i列是否可以放置皇后{vector<vector<int>> tmp = attack;//备份attack数组queen[k][i] = 'Q';//标记该位置为Qput_queen(k, i, attack);//更新attack数组backtrack(k + 1, n, queen, attack, solve);//递归试探k+1⾏的皇后的位置attack = tmp;//恢复attack数组queen[k][i] = '.';//恢复queen数组}}}vector<vector<string>>solveNQueens(int n){//string存储具体的摆放位置,<vector<string>>存放⼀种解法,⼆维vector存放全部解法vector<vector<string>>solve;//存储最后结果vector<vector<int>>attack;//标记皇后的攻击位vector<string>queen;//保存皇后位置//使⽤循环初始化attack和queen数组for (int i = 0; i < n; i++){attack.push_back((vector<int>()));for (int j = 0; j < n; j++){attack[i].push_back(0);}queen.push_back("");queen[i].append(n, '.');}backtrack(0, n, queen, attack, solve);return solve;//返回结果数组}int main(){//int num;//cin >> num;//输⼊皇后数初始化attack数组//vector<vector<int>> attack(num,vector<int>(num, 0));初始化queen数组//string s;//for (int i = 0; i < num; i++)s += '.';//vector<string> queen(num, s);int n;cin >> n;vector<vector<string>>result;result = solveNQueens(n);cout << n << "皇后共有" << result.size() << "种解法" << endl;for (int i = 0; i < result.size(); i++){cout << "解法" << i + 1 << ":" << endl;for (int j = 0; j < result[i].size(); j++){cout << result[i][j] << endl;}cout << endl;}system("pause");return 0;}四、测试结果四皇后⼋皇后到此这篇关于C语⾔回溯法解⼋皇后问题的⽂章就介绍到这了。

C语言经典算法大全(可编辑)

C语言经典算法大全(可编辑)

C语言经典算法大全C语言经典算法大全老掉牙河内塔费式数列巴斯卡三角形三色棋老鼠走迷官一老鼠走迷官二骑士走棋盘八个皇后八枚银币生命游戏字串核对双色三色河内塔背包问题Knapsack Problem数运算蒙地卡罗法求 PIEratosthenes筛选求质数超长整数运算大数运算长 PI最大公因数最小公倍数因式分解完美数阿姆斯壮数最大访客数中序式转后序式前序式后序式的运算关于赌博洗扑克牌乱数排列Craps赌博游戏约瑟夫问题Josephus Problem 集合问题排列组合格雷码Gray Code产生可能的集合m元素集合的n个元素子集数字拆解排序得分排行选择插入气泡排序Shell 排序法 - 改良的插入排序Shaker 排序法 - 改良的气泡排序Heap 排序法 - 改良的选择排序快速排序法一快速排序法二快速排序法三合并排序法基数排序法搜寻循序搜寻法使用卫兵二分搜寻法搜寻原则的代表插补搜寻法费氏搜寻法矩阵稀疏矩阵多维矩阵转一维矩阵上三角下三角对称矩阵奇数魔方阵4N 魔方阵2 2N1 魔方阵 1河内之塔说明河内之塔 Towers of Hanoi 是法国人MClaus Lucas 于1883年从泰国带至法国的河内为越战时北越的首都即现在的胡志明市1883年法国数学家 Edouard Lucas曾提及这个故事据说创世纪时Benares有一座波罗教塔是由三支钻石棒Pag所支撑开始时神在第一根棒上放置64个由上至下依由小至大排列的金盘Disc并命令僧侣将所有的金盘从第一根石棒移至第三根石棒且搬运过程中遵守大盘子在小盘子之下的原则若每日仅搬一个盘子则当盘子全数搬运完毕之时此塔将毁损而也就是世界末日来临之时解法如果柱子标为ABC要由A搬至C在只有一个盘子时就将它直接搬至C当有两个盘子就将B当作辅助柱如果盘数超过2个将第三个以下的盘子遮起来就很简单了每次处理两个盘子也就是A- BA - CB- C这三个步骤而被遮住的部份其实就是进入程式的递回处理事实上若有n个盘子则移动完毕所需之次数为2n - 1所以当盘数为64时则所需次数为264- 1 1XXXXXXXXXX709551615为505390248594782e16年也就是约5000世纪如果对这数字没什幺概念就假设每秒钟搬一个盘子好了也要约5850亿年左右includevoid hanoi int n char A char B char Cif n 1printf "Move sheet d from c to c\n" n A Celsehanoi n-1 A C Bprintf "Move sheet d from c to c\n" n A Chanoi n-1 B A Cint mainint nprintf "请输入盘数"scanf "d" nhanoi n A B Cfn fn-1 fn-2 if n 1fn n if n 0 1includeinclude define N 20 int main voidint Fib[N] 0int i Fib[0] 0Fib[1] 1 for i 2 i N iFib[i] Fib[i-1] Fib[i-2] for i 0 i N i printf "d " Fib[i]printf "\n"return 03 巴斯卡三角形 includedefine N 12long combi int n int rint ilong p 1for i 1 i r ip p n-i1 ireturn pvoid mainint n r tfor n 0 n N nfor r 0 r n rint i 排版设定开始if r 0for i 0 i N-n i printf " "elseprintf " "排版设定结束printf "3d" combi n rprintf "\n"4Algorithm Gossip 三色棋说明三色旗的问题最早由EWDijkstra所提出Dutch Nation Flag Dijkstra为荷兰人 Three-Color Flag来称之假设有一条绳子上面有红白蓝三种颜色的旗子起初绳子上的旗子颜色并没有顺序您希望将之分类并排列为蓝白红的顺序要如何移动次数才会最少注意您只能在绳子上进行这个动作而且一次只能调换两个旗子解法在一条绳子上移动在程式中也就意味只能使用一个阵列而不使用其它的阵列来作辅助问题的解法很简单您可以自己想像一下在移动旗子从绳子开头进行遇到蓝色往前移遇到白色留在中间遇到红色往后移如下所示只是要让移动次数最少的话就要有些技巧如果图中W所在的位置为白色则W1表示未处理的部份移至至白色群组如果W部份为蓝色则B与W的元素对调而B与W必须各1表示两个群组都多了一个元素如果W所在的位置是红色则将W与R交换但R要减1表示未处理的部份减1 注意BWR并不是三色旗的个数它们只是一个移动的指标什幺时候移动结束呢一开始时未处理的R指标会是等于旗子的总数当R的索引数减至少于W的索引数时表示接下来的旗子就都是红色了此时就可以结束移动如下所示 includeincludeinclude define BLUE bdefine WHITE wdefine RED r define SWAP x y char temp \temp color[x] \color[x] color[y] \color[y] temp int main char color[] r w b w wb r b w r \0 int wFlag 0 int bFlag 0int rFlag strlen color - 1int i for i 0 i strlen color iprintf "c " color[i]printf "\n" while wFlag rFlagif color[wFlag] WHITEwFlagelse if color[wFlag] BLUESWAP bFlag wFlagbFlag wFlagelsewhile wFlag rFlag color[rFlag] REDrFlag--SWAP rFlag wFlagrFlag--for i 0 i strlen color i printf "c " color[i]printf "\n" return 05Algorithm Gossip 老鼠走迷官说明老鼠走迷宫是递回求解的基本题型我们在二维阵列中使用2表示迷宫墙壁使用1来表示老鼠的行走路径试以程式求出由入口至出口的路径解法老鼠的走法有上左下右四个方向在每前进一格之后就选一个方向前进无法前进时退回选择下一个可前进方向如此在阵列中依序测试四个方向直到走到出口为止这是递回的基本题请直接看程式应就可以理解includeinclude int visit int int int maze[7][7] 2 2 2 22 2 22 0 0 0 0 0 22 0 2 0 2 0 22 0 0 2 0 2 22 2 0 2 0 2 22 0 0 0 0 0 22 2 2 2 2 2 2 int startI 1 startJ 1 入口int endI 5 endJ 5 出口int success 0 int main voidint i j printf "显示迷宫\n"for i 0 i 7 ifor j 0 j 7 jif maze[i][j] 2printf "█"elseprintf " "printf "\n"if visit startI startJ 0 printf "\n没有找到出口\n"elseprintf "\n\n"for i 0 i 7 ifor j 0 j 7 jif maze[i][j] 2printf "█"else if maze[i][j] 1 printf "◇"elseprintf " "printf "\n"return 0int visit int i int jmaze[i][j] 1 if i endI j endJsuccess 1 if success 1 maze[i][j1]0 visit i j1if success 1 maze[i1][j] 0 visit i1 jif success 1 maze[i][j-1] 0 visit i j-1if success 1 maze[i-1][j] 0 visit i-1 j if success 1maze[i][j] 0 return success6Algorithm Gossip 老鼠走迷官说明由于迷宫的设计老鼠走迷宫的入口至出口路径可能不只一条如何求出所有的路径呢解法求所有路径看起来复杂但其实更简单只要在老鼠走至出口时显示经过的路径然后退回上一格重新选择下一个位置继续递回就可以了比求出单一路径还简单我们的程式只要作一点修改就可以了includeinclude void visit int int int maze[9][9] 2 2 2 22 2 2 2 22 0 0 0 0 0 0 0 22 0 2 2 0 2 2 0 22 0 2 0 0 2 0 0 22 0 2 0 2 0 2 0 22 0 0 0 0 0 2 0 22 2 0 2 2 0 2 2 22 0 0 0 0 0 0 0 22 2 2 2 2 2 2 2 2 int startI 1 startJ 1 入口int endI 7 endJ 7 出口 int main voidint i j printf "显示迷宫\n"for i 0 i 7 ifor j 0 j 7 jif maze[i][j] 2printf "█"elseprintf " "printf "\n"visit startI startJ return 0void visit int i int jint m n maze[i][j] 1 if i endI j endJprintf "\n显示路径\n"for m 0 m 9 mfor n 0 n 9 nif maze[m][n] 2printf "█"else if maze[m][n] 1printf "◇"elseprintf " "printf "\n"if maze[i][j1] 0 visit i j1if maze[i1][j] 0 visit i1 jif maze[i][j-1] 0 visit i j-1if maze[i-1][j] 0 visit i-1 j maze[i][j] 07Algorithm Gossip 骑士走棋盘说明骑士旅游Knight tour[所有的位置include int board[8][8] 0 int main voidint startx startyint i jprintf "输入起始点"scanf "d d" startx starty if travel startx starty printf "\n"elseprintf "\n"for i 0 i 8 ifor j 0 j 8 jprintf "2d " board[i][j]putchar \nreturn 0int travel int x int yint ktmove1[8] -2 -1 1 2 2 1 -1 -2int ktmove2[8] 1 2 2 1 -1 -2 -2 -1 测试下一步的出路int nexti[8] 0int nextj[8] 0记录出路的个数int exists[8] 0int i j k m lint tmpi tmpjint count min tmp i xj yboard[i][j] 1 for m 2 m 64 mfor l 0 l 8 lexists[l] 0 l 0 试探八个方向for k 0 k 8 ktmpi i ktmove1[k]tmpj j ktmove2[k] 如果是边界了if tmpi 0 tmpj 0 tmpi 7 tmpj 7 continue 如果这个方向可走 if board[tmpi][tmpj] 0nexti[l] tmpinextj[l] tmpj可走的方向加一个lcount l如果可走的方向为0个if count 0return 0else if count 1只有一个可走的方向所以直接是最少出路的方向min 0else找出下一个位置的出路数for l 0 l count lfor k 0 k 8 ktmpi nexti[l] ktmove1[k] tmpj nextj[l] ktmove2[k] if tmpi 0 tmpj 0tmpi 7 tmpj 7continueif board[tmpi][tmpj] 0 exists[l]tmp exists[0]min 0从可走的方向中寻找最少出路的方向 for l 1 l count lif exists[l] tmptmp exists[l]min l走最少出路的方向i nexti[min]j nextj[min]board[i][j] mreturn 18Algorithm Gossip 八皇后说明西洋棋中的皇后可以直线前进吃掉遇到的所有棋子如果棋盘上有八个皇后则这八个皇后如何相安无事的放置在棋盘上1970年与1971年 EWDijkstra与NWirth曾经用这个问题来讲解程式设计之技巧解法关于棋盘的问题都可以用递回求解然而如何减少递回的次数在八个皇后的问题中不必要所有的格子都检查过例如若某列检查过该该列的其它格子就不用再检查了这个方法称为分支修剪includeincludedefine N 8 int column[N1] 同栏是否有皇后1int rup[2N1] 右上至左下是否有皇后int lup[2N1] 左上至右下是否有皇后int queen[N1] 0int num 解答编号 void backtrack int 递回求解 intmain voidint inum 0 for i 1 i N icolumn[i] 1 for i 1 i 2N irup[i] lup[i] 1 backtrack 1 return 0void showAnswerint x yprintf "\n解答 d\n" numfor y 1 y N yfor x 1 x N xif queen[y] xprintf " Q"elseprintf " "printf "\n"void backtrack int iint j if i NshowAnswerelsefor j 1 j N jif column[j] 1rup[ij] 1 lup[i-jN] 1 queen[i] j设定为占用column[j] rup[ij] lup[i-jN] 0 backtrack i1column[j] rup[ij] lup[i-jN] 19Algorithm Gossip 八枚银币说明现有八枚银币a b c d e f g h已知其中一枚是假币其重量不同于真币但不知是较轻或较重如何使用天平以最少的比较次数决定出哪枚是假币并得知假币比真币较轻或较重解法单就求假币的问题是不难但问题限制使用最少的比较次数所以我们不能以单纯的回圈比较来求解我们可以使用决策树decision tree使用分析与树状图来协助求解一个简单的状况是这样的我们比较abc与def 如果相等则假币必是g或h我们先比较g或h哪个较重如果g较重再与a比较a是真币如果g等于a则g为真币则h为假币由于h比g轻而 g是真币则h假币的重量比真币轻 include includeinclude void compare int[] int int intvoid eightcoins int[] int main voidint coins[8] 0int i srand time NULL for i 0 i 8 icoins[i] 10 printf "\n输入假币重量比10大或小 "scanf "d" icoins[rand 8] i eightcoins coins printf "\n\n"for i 0 i 8 iprintf "d " coins[i] printf "\n"return 0void compare int coins[] int i int j int kif coins[i] coins[k]printf "\n d 较重" i1elseprintf "\n假币 d 较轻" j1void eightcoins int coins[]if coins[0]coins[1]coins[2]coins[3]coins[4]coins[5]if coins[6] coins[7]compare coins 6 7 0elsecompare coins 7 6 0else if coins[0]coins[1]coins[2]coins[3]coins[4]coins[5]if coins[0]coins[3] coins[1]coins[4]compare coins 2 5 0else if coins[0]coins[3] coins[1]coins[4] compare coins 0 4 1if coins[0]coins[3] coins[1]coins[4]compare coins 1 3 0else if coins[0]coins[1]coins[2]coins[3]coins[4]coins[5]if coins[0]coins[3] coins[1]coins[4]compare coins 5 2 0else if coins[0]coins[3] coins[1]coins[4] compare coins 3 1 0if coins[0]coins[3] coins[1]coins[4]compare coins 4 0 110Algorithm Gossip 生命游戏说明生命游戏game of life1970年由英国数学家J H Conway所提出includeincludeinclude define ROW 10define COL 25define DEAD 0define ALIVE 1int map[ROW][COL] newmap[ROW][COL] void initint neighbors int intvoid outputMapvoid copyMap int mainint row colchar ansinitwhile 1outputMapfor row 0 row ROW rowfor col 0 col COL colswitch neighbors row colcase 0case 1case 4case 5case 6case 7case 8newmap[row][col] DEADbreakcase 2newmap[row][col] map[row][col] breakcase 3newmap[row][col] ALIVEbreakcopyMapprintf "\nContinue next Generation "getcharans toupper getcharif ans Y breakreturn 0void initint row col for row 0 row ROW rowfor col 0 col COL colmap[row][col] DEAD puts "Game of life Program"puts "Enter x y where x y is living cell"printf "0 x d 0 y d\n"ROW-1 COL-1puts "Terminate with x y -1 -1" while 1scanf "d d" row colif 0 row row ROW0 col col COLmap[row][col] ALIVEelse if row -1 col -1breakelseprintf " x y exceeds map ranage"int neighbors int row int colint count 0 c rfor r row-1 r row1 rfor c col-1 c col1 cif r 0 r ROW c 0 c COL continueif map[r][c] ALIVEcountif map[row][col] ALIVEcount--return countvoid outputMapint row colprintf "\n\n20cGame of life cell status\n" for row 0 row ROW rowprintf "\n20c"for col 0 col COL colif map[row][col] ALIVE putchar else putchar -void copyMapint row colfor row 0 row ROW rowfor col 0 col COL colmap[row][col] newmap[row][col]11Algorithm Gossip 字串核对说明今日的一些高阶程式语言对于字串的处理支援越来越强大例如JavaPerl等不过字串搜寻本身仍是个值得探讨的课题在这边以Boyer- Moore法来说明如何进行字串说明这个方法快且原理简洁易懂解法字串搜寻本身不难使用暴力法也可以求解但如何快速搜寻字串就不简单了传统的字串搜寻是从关键字与字串的开头开始比对例如 Knuth-Morris-Pratt 演算法字串搜寻这个方法也不错不过要花时间在公式计算上Boyer-Moore字串核对改由关键字的后面开始核对字串并制作前进表如果比对不符合则依前进表中的值前进至下一个核对处假设是p好了然后比对字串中p-n1至p的值是否与关键字相同如果关键字中有重复出现的字元则前进值就会有两个以上的值此时则取前进值较小的值如此就不会跳过可能的位置例如texture 这个关键字t的前进值应该取后面的3而不是取前面的7 includeincludeinclude void table char 建立前进表int search int char char 搜寻关键字void substring char char int int 取出子字串int skip[256] int main voidchar str_input[80]char str_key[80]char tmp[80] \0int m n pprintf "请输入字串"gets str_inputprintf ""gets str_keym strlen str_inputn strlen str_keytable str_keyp search n-1 str_input str_key while p -1 substring str_input tmp p mprintf "s\n" tmpp search pn1 str_input str_keyprintf "\n"return 0void table char keyint k nn strlen keyfor k 0 k 255 kskip[k] nfor k 0 k n - 1 kskip[key[k]] n - k - 1int search int p char input char keyint i m nchar tmp[80] \0m strlen inputn strlen key while p msubstring input tmp p-n1 pif strcmp tmp key 比较两字串是否相同return p-n1p skip[input[p]]return -1void substring char text char tmp int s int e int i jfor i s j 0 i e i jmp[j] text[i]tmp[j] \012Algorithm Gossip 双色三色河内塔说明双色河内塔与三色河内塔是由之前所介绍过的河内塔规则衍生而来双色河内塔的目的是将下图左上的圆环位置经移动成为右下的圆环位置而三色河内塔则是将下图左上的圆环经移动成为右上的圆环解法无论是双色河内塔或是三色河内塔其解法观念与之前介绍过的河内塔是类似的同样也是使用递回来解不过这次递回解法的目的不同我们先来看只有两个盘的情况这很简单只要将第一柱的黄色移动至第二柱而接下来第一柱的蓝色移动至第三柱再来是四个盘的情况首先必须用递回完成下图左上至右下的移动接下来最底层的就不用管它们了因为它们已经就定位只要再处理第一柱的上面两个盘子就可以了那么六个盘的情况呢一样首先必须用递回完成下图左上至右下的移动接下来最底层的就不用管它们了因为它们已经就定位只要再处理第一柱上面的四个盘子就可以了这又与之前只有四盘的情况相同接下来您就知道该如何进行解题了无论是八个盘十个盘以上等都是用这个观念来解题那么三色河内塔呢一样直接来看九个盘的情况首先必须完成下图的移动结果接下来最底两层的就不用管它们了因为它们已经就定位只要再处理第一柱上面的三个盘子就可以了双色河内塔 C 实作include void hanoi int disks char source char temp char targetif disks 1printf "move disk from c to c\n" source targetprintf "move disk from c to c\n" source target elsehanoi disks-1 source target temphanoi 1 source temp targethanoi disks-1 temp source targetvoid hanoi2colors int diskschar source Achar temp Bchar target Cint ifor i disks 2 i 1 i--hanoi i-1 source temp targetprintf "move disk from c to c\n" source temp printf "move disk from c to c\n" source temp hanoi i-1 target temp sourceprintf "move disk from c to c\n" temp targetprintf "move disk from c to c\n" source tempprintf "move disk from c to c\n" source targetint mainint nprintf "请输入盘数"scanf "d" n hanoi2colors n return 0C 实作include void hanoi int disks char source char temp char targetif disks 1printf "move disk from c to c\n" source target printf "move disk from c to c\n" source target printf "move disk from c to c\n" source target elsehanoi disks-1 source target temphanoi 1 source temp targethanoi disks-1 temp source targetvoid hanoi3colors int diskschar source Achar temp Bchar target Cint iif disks 3printf "move disk from c to c\n" source tempprintf "move disk from c to c\n" source tempprintf "move disk from c to c\n" source targetprintf "move disk from c to c\n" temp targetprintf "move disk from c to c\n" temp sourceprintf "move disk from c to c\n" target tempelsehanoi disks3-1 source temp targetprintf "move disk from c to c\n" source tempprintf "move disk from c to c\n" source tempprintf "move disk from c to c\n" source temp hanoi disks3-1 target temp sourceprintf "move disk from c to c\n" temp targetprintf "move disk from c to c\n" temp targetprintf "move disk from c to c\n" temp target hanoi disks3-1 source target tempprintf "move disk from c to c\n" target sourceprintf "move disk from c to c\n" target source hanoi disks3-1 temp source targetprintf "move disk from c to c\n" source temp for i disks 3 - 1 i 0 i--if i 1hanoi i-1 target source tempprintf "move disk from c to c\n"target source printf "move disk from c to c\n"target source if i 1hanoi i-1 temp source targetprintf "move disk from c to c\n" source tempint mainint nprintf "请输入盘数"scanf "d" n hanoi3colors nreturn 013Algorithm Gossip 背包问题Knapsack Problem说明假设有一个背包的负重最多可达8公斤而希望在背包中装入负重范围内可得之总价物品假设是水果好了水果的编号单价与重量如下所示0 李子 4KG NT4500 1 苹果 5KG NT57002 橘子 2KG NT22503 草莓 1KG NT1100 4甜瓜 6KG NT6700解法背包问题是关于最佳化的问题要解最佳化问题可以使用「动态规划」Dynamic programming从空集合开始每增加一个元素就先求出该阶段的最佳解直到所有的元素加入至集合中最后得到的就是最佳解以背包问题为例我们使用两个阵列value与itemvalue表示目前的最佳解所得之总价item表示最后一个放至背包的水果假设有负重量 1~8的背包8个并对每个背包求其最佳解逐步将水果放入背包中并求该阶段的最佳解放入李子背包负重 1 2 3 4 5 6 7 8 value 0004500 4500 4500 4500 9000 item ---00000放入苹果背包负重 1 2 3 4 5 6 7 8 value 0004500 5700 5700 5700 9000 item ---0 1 1 1 0放入橘子背包负重 1 2 3 4 5 6 7 8 value 02250 2250 4500 5700 6750 7950 9000 item -2 2 0 1 2 2 0放入草莓背包负重 1 2 3 4 5 6 7 8 value 11002250 3350 4500 5700 6800 7950 9050 item 3 23 0 1 3 2 3放入甜瓜背包负重 1 2 3 4 5 6 7 8 value 11002250 3350 4500 5700 6800 7950 9050 item 3 23 0 1 3 2 3由最后一个表格可以得知在背包负重8公斤时最多可以装入9050元的水果而最后一个装入的水果是3号也就是草莓装入了草莓背包只能再放入7公斤8-1的水果所以必须看背包负重7公斤时的最佳解最后一个放入的是2号也就是橘子现在背包剩下负重量5公斤7-2所以看负重5公斤的最佳解最后放入的是1号也就是苹果此时背包负重量剩下0公斤5-5无法再放入水果所以求出最佳解为放入草莓橘子与苹果而总价为9050元实作 Cincludeinclude define LIMIT 8 重量限制define N 5 物品种类define MIN 1 最小重量 struct bodychar name[20]int sizeint pricetypedef struct body object int main voidint item[LIMIT1] 0int value[LIMIT1] 0int newvalue i s p object a[] "李子" 4 4500 "苹果" 5 5700"橘子" 2 2250"草莓" 1 1100"甜瓜" 6 6700 for i 0 i N i for s a[i]size s LIMIT sp s - a[i]sizenewvalue value[p] a[i]priceif newvalue value[s] 找到阶段最佳解value[s] newvalueitem[s] iprintf "物品\t价格\n"for i LIMIT i MIN i i - a[item[i]]sizeprintf "s\td\n"a[item[i]]name a[item[i]]priceprintf "合计\td\n" value[LIMIT] returnJavaclass Fruitprivate String nameprivate int sizeprivate int price public Fruit String name int size int pricethisname namethissize sizethisprice pricepublic String getNamereturn namepublic int getPricereturn pricepublic int getSizereturn sizepublic class Knapsackpublic static void main String[] argsfinal int 8final int MIN 1int[] item new int[1]int[] value new int[1] Fruit fruits[]new Fruit "李子" 4 4500new Fruit "苹果" 5 5700new Fruit "橘子" 2 2250new Fruit "草莓" 1 1100new Fruit "甜瓜" 6 6700 fo。

数据结构C语言版_八皇后

数据结构C语言版_八皇后
* * * * @ * * *
第10种状态为:
* @ * * * * * *
* * * * * * @ *
* * @ * * * * *
* * * * * @ * *
* * * * * * * @
* * * * @ * * *
@ * * * * * * *
* * * @ * * * *
if(i<7)
qu(i+1); //如果行还没有遍历完,进入下一行
else //否则输出
{
//输出棋盘状态
int iLine,iColumn;
printf("第%d种状态为:\n",++iQueenNum);
for(iLine=0;iLine<8;iLine++)
* * * * @ * * *
* * * * * * * @
* @ * * * * * *
* * * @ * * * *
* * * * * @ * *
* * @ * * * * *
第5种状态为:
* @ * * * * * *
* * * @ * * * *
* * * * * @ * *
* * @ * * * * *
* * * * @ * * *
第9种状态为:
* @ * * * * * *
* * * * * @ * *
* * * * * * * @
* * @ * * * * *
@ * * * * * * *
* * * @ * * * *
* * * * * * @ *
{

八皇后问题c语言代码

八皇后问题c语言代码

八皇后问题c语言代码八皇后问题是经典的回溯算法问题,下面是一个简单的C语言代码示例来解决八皇后问题:c.#include <stdio.h>。

#include <stdbool.h>。

#define N 8。

int board[N][N];void printSolution() {。

for (int i = 0; i < N; i++) {。

for (int j = 0; j < N; j++) {。

printf("%d ", board[i][j]); }。

printf("\n");}。

}。

bool isSafe(int row, int col) {。

int i, j;for (i = 0; i < col; i++) {。

if (board[row][i]) {。

return false;}。

}。

for (i = row, j = col; i >= 0 && j >= 0; i--, j--) {。

if (board[i][j]) {。

return false;}。

}。

for (i = row, j = col; j >= 0 && i < N; i++, j--) {。

if (board[i][j]) {。

return false;}。

}。

return true;}。

bool solveNQUtil(int col) {。

if (col >= N) {。

return true;}。

for (int i = 0; i < N; i++) {。

if (isSafe(i, col)) {。

board[i][col] = 1;if (solveNQUtil(col + 1)) {。

return true;}。

board[i][col] = 0;}。

八皇后问题详细的解法

八皇后问题详细的解法
八皇后问题
1
1八皇后问题背景 2盲目的枚举算法 3加约束的枚举算法 4回溯法及基本思想 5 回溯法应用 6八皇后问题的递归回溯算法 7八皇后问题的非递归回溯算法
2
【背景】 八皇后问题是一个以国际象棋为背
景的问题: 如何能够在 8×8 的国际象棋棋盘上
放置八个皇后,使得任何一个皇后都 无法直接吃掉其他的皇后?为了达到 此目的,任两个皇后都不能处于同一 条横行、纵行或斜线上。
}
}
23
20
2 回溯法应用-算法框架-递归算法框架
int a[n]; Queens(int k) { if (k>n) 即表示最后一个皇后摆放完毕,输出结果;
else for(i=下界 ; i<=上界; i++) //枚举K个皇后所有可能的路径 {依次从列顶端开始搜索,一直到列底端,直到找到合适位置,如
果未找到,自动返回上层递归
的,能避免不必要搜索的穷举式搜索法。这种方法适 用于解一些组合数相当大的问题。 回溯法在问题的解空间树中,按深度优先策略,从根 结点出发搜索解空间树。算法搜索至解空间树的任意 一点时,先判断该结点是否包含问题的解。如果肯定 不包含,则跳过对该结点为根的子树的搜索,逐层向 其祖先结点回溯;否则,进入该子树,继续按深度优 先策略搜索。
for(a[8]=1;a[8]<=8;a[8]++) 此算法可读性很好,
{if (check(a,8)==0)continue; 体现了“回溯”。但
else for(i=1;i<=8;i++) 它只能解决八皇后问
print(a[i]); }
题,而不能解决任意
}}}}}}}

C语言实现全排列和回溯法总结

C语言实现全排列和回溯法总结

C语⾔实现全排列和回溯法总结⼀、递归实现全排列1 #include"cstdio"2int A[50];3void print_permutation(int n,int *A,int cur){4if(cur==n){5for(int i=0;i<n;i++)6 printf("%d",A[i]);7 printf("\n");8 }9else for(int j=1;j<n+1;j++){10int ok=1;11for(int k=0;k<cur;k++)12if(A[k]==j)13 ok=0;14if(ok){15 A[cur]=j;16 print_permutation(n,A,cur+1);17 }18 }19 }20int main(){21int n;22 scanf("%d",&n);23 print_permutation(n,A,0);24return0;25 }View Code⼆、解答树1 #include <string.h>2 #include <iostream>34using namespace std;5const int N = 99999999; //输⼊排序的个数的最⼤值6int record[N]; //记录每次排序的序列7int visited[N]; //标记节点是否被访问过8int n; //输⼊节点的数⽬9int totalSize = 0;10void DFS(int start){11if(start>=n){ //递归出⼝12for(int i=0;i<n;i++){13 cout<<record[i]<<"";14 }15 totalSize++;16 cout<<endl;17return;18 }19for(int i=1;i<=n;i++){ //深度遍历节点,并标记已经访问过的节点20if(visited[i]==0){21 visited[i] = 1;22 record[start] = i;23 DFS(start+1); //递归遍历24 visited[i] = 0; //回退时标记回退的节点为未被访问节点25 }26 }27 }2829int main()30 {31 cin>>n;32 memset(visited,0,n);33 DFS(0);34 cout<<"totalSize = "<<totalSize<<endl;35return0;36 }View Code三、调⽤next_permutation()⽅法四、回溯法总结1、⼋皇后问题代码1 #include<iostream>2 #include<math.h>3using namespace std;4int n=8; 5int rows[8];//存储n⾏的第⼏列6int j=0;7bool Is(int row){8for(int i=1;i<row+1;i++){9if(rows[row-i]==rows[row]-i||rows[row-i]==rows[row]+i||rows[row]==rows[row-i]) 10return false;11 }12return true;13 }14void start(int row){15if(row==n)16 j++;17else {18for(int col=0;col<n;col++){19 rows[row]=col;20if(Is(row)){21 printf("%d %d\n",row,rows[row]);22 start(row+1);23 }24 }25 }26 }27int main(){28 start(0);29 printf("%d\n",j);30return0;31 }总结:在全排列和⼋皇后问题中,均使⽤了递归回溯。

八皇后问题的n种解法

八皇后问题的n种解法

⼋皇后问题的n种解法经典的⼋皇后问题:在8×8格的国际象棋上摆放⼋个皇后,使其不能互相攻击,即任意两个皇后都不能处于同⼀⾏、同⼀列或同⼀斜线上,问有多少种摆法。

很早就接触过⼋皇后问题,最近数据结构作业中⼜看到了这个题⽬,仔细研究了⼀波⽹上诸位⼤⽜的博客,发现这个问题居然有这么多有趣的优化。

1.经典的回溯递归解法:#include<stdio.h>#include<iostream>using namespace std;//dfs,每⾏只能放⼀个元素,遍历每⾏的每个位置,⽤⼀个⼀维数组记录,最后检查是否符合要求int ans;int vis[10];int abs(int x){return x > 0 ? x : -x;}bool check(int r,int c){for(int i = 1;i<r;i++){if(vis[i] == c) return false;if(vis[i] - c == r - i || vis[i] - c == i - r) return false;}return true;}void dfs(int r){if(r > 8){ans++;return;}for(int i = 1;i<=8;i++){if(check(r,i)){vis[r] = i;dfs(r+1);vis[r] = 0;}}}main(){dfs(1);cout<<ans<<endl;}2.对⾓线检查优化/*⽤三个数组记录列,左对⾓线,右对⾓线信息,每次判断该位置是否符合要求,只在符合要求位置放置元素。

*/#include <iostream>using namespace std;const int maxn=105;const int mo=100;typedef long long ll;int a[maxn],n = 8,ans=0;bool b[maxn],c[maxn],d[maxn];void sou(int x){if(x > n){ans++;return;}for(int i = 1;i <= n;i++)if(!(b[i] || c[x+i] || d[x-i+n])){b[i] =c [x+i]=d[x-i+n]=true;a[x] = i;sou(x+1);b[i] =c [x+i] = d[x-i+n]=false;}}int main(){sou(1);cout<<ans;}3.位运算://算法思想与上⼀相同,改⽤三个int来存储信息,采⽤位运算提取合适位置#include<iostream>#include<stdio.h>using namespace std;int board;int n;int ans = 0;void n_queen(int col,int ld,int rd){if(col == board){ans++;return;}int pos = board & (~(col | ld | rd));while(pos){int p = pos & (-pos);pos = pos - p;n_queen(col | p , (ld | p) << 1,(rd | p) >> 1);}}int main(){cin>>n;board = (1 << n) - 1;n_queen(0,0,0);cout<<ans<<endl;}4.⼗⾏内的⼋皇后...对知乎上各路⼤⼤的炫技佩服的五体投地,更改了⼀下上⼀代码,勉强也达到了⼗⾏的要求。

C语言八皇后问题

C语言八皇后问题

C语言八皇后问题C语言八皇后问题八皇后问题是一个古老而著名的问题。

该问题是19世纪著名的数学家高斯1850年提出:在一个8*8国际象棋盘上,有8个皇后,每个皇后占一格;要求皇后之间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行、同一列或同一对角线上。

问共有多少种不同的方法?回溯算法也叫试探法,它是一种搜索问题的解的方法。

冋溯算法的基本思想是在一个包含所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。

算法搜索至解空间树的任意结点时,总是先判断该结点是否肯定不包含问题的解。

如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。

否则,进入该子树,继续按深度优先的策略进行搜索。

回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。

八皇后问题有很多中解法,其中使用回溯法进行求解是其中一种。

而回溯发也是最直接的一种解法,也较容易理解。

八皇后问题的回溯法算法,可以采用一维数组来进行处理。

数组的下标i表示棋盘上的第i列,a[i]的值表示皇后在第i列所放的位置。

例如,a[1]=5,表示在棋盘的第例的第五行放一个皇后。

程序中首先假定a[1]=1,表示第一个皇后放在棋盘的第一列的第一行的位置上,然后试探第二列中皇后可能的位置,找到合适的位置后,再处理后续的各列,这样通过各列的反复试探,可以最终找出皇后的全部摆放方法。

八皇后问题可以使用回溯法进行求解,程序实现如下:#include#define Queens 8 //定义结果数组的大小,也就是皇后的数目int a[Queens+1]; //八皇后问题的皇后所在的行列位置,从1幵始算起,所以加1int main(){int i, k, flag, not_finish=1, count=0;//正在处理的.元素下标,表示前i-1个元素已符合要求,正在处理第i个元素i=1;a[1]=1; //为数组的第一个元素赋初值printf("The possible configuration of 8 queens are:\n");while(not_finish){ //not_finish=l:处理尚未结束while(not_finish && i<=Queens){ //处理尚未结束且还没处理到第Queens个元素for(flag=1,k=1; flag && kif(a[k]==a[i])flag=0;for (k=1; flag&&kif( (a[i]==a[k]-(k-i)) || (a[i]==a[k]+(k-i)) )flag=0;if(!flag){ //若存在矛盾不满足要求,需要重新设置第i个元素if(a[i]==a[i-1]){ //若a[i]的值已经经过一圈追上a[i-1]的值i--; //退回一步,重新试探处理前一个元素if(i>1 && a[i]==Queens)a[i]=1; //当a[i]为Queens时将a[i]的值置1elseif(i==1 && a[i]==Queens)not_finish=0; //当第一位的值达到Queens时结束elsea[i]++; //将a[il的值取下一个值}else if(a[i] == Queens)a[i]=1;elsea[i]++; //将a[i]的值取下一个值}else if(++i<=Queens)if(a[i-1] == Queens )a[i]=1; //若前一个元素的值为Queens则a[i]=lelsea[i] = a[i-1]+1; //否则元素的值为前一个元素的下一个值}if(not_finish){++count;printf((count-1)%3 ? "\t[%2d]:" : "\n[%2d]:", count);for(k=1; k<=Queens; k++) //输出结果printf(" %d", a[k]);if(a[Queens-1]a[Queens-1]++; //修改倒数第二位的值elsea[Queens-1]=1;i=Queens -1; //开始寻找下一个满足条件的解}}}输出结果:The possible configuration of 8 queens are:[ 1]: 1 5 8 6 3 7 2 4 [ 2]: 1 6 8 3 7 4 2 5 [ 3]: 1 7 4 6 8 2 5 3 [ 4]: 1 7 5 8 2 4 6 3 [ 5]: 2 4 6 8 3 1 7 5 [ 6]: 2 5 7 1 3 8 6 4 [ 7]: 2 5 7 4 1 8 6 3 [ 8]: 2 6 8 3 1 4 7 5 [ 9]: 2 6 1 7 4 8 3 5 [10]: 2 7 3 6 8 5 1 4 [11]: 2 7 5 8 1 4 6 3 [12]: 2 8 6 1 3 5 7 4 [13]: 3 5 7 1 4 2 8 6 [14]: 3 5 8 4 1 7 2 6 [15]: 3 5 2 8 1 7 4 6 [16]: 3 5 2 8 6 4 7 1 [17]: 3 6 8 1 4 7 5 2 [18]: 3 6 8 1 5 7 2 4 [19]: 3 6 8 2 4 1 7 5 [20]: 3 6 2 5 8 1 7 4 [21]: 3 6 2 7 1 4 8 5 [22]: 3 6 2 7 5 1 8 4 [23]: 3 6 4 1 8 5 7 2 [24]: 3 6 4 2 8 5 7 1 [25]: 3 7 2 8 5 1 4 6 [26]: 3 7 2 8 6 4 1 5 [27]: 3 8 4 7 1 6 2 5 [28]: 3 1 7 5 8 2 4 6 [29]: 4 6 8 2 7 1 3 5 [30]: 4 6 8 3 1 7 5 2[31]: 4 6 1 5 2 8 3 7 [32]: 4 7 1 8 5 2 6 3 [33]: 4 7 3 8 2 5 1 6 [34]: 4 7 5 2 6 1 3 8 [35]: 4 7 5 3 1 6 8 2 [36]: 4 8 1 3 6 2 7 5 [37]: 4 8 1 5 7 2 6 3 [38]: 4 8 5 3 1 7 2 6 [39]: 4 1 5 8 2 7 3 6 [40]: 4 1 5 8 6 3 7 2 [41]: 4 2 5 8 6 1 3 7 [42]: 4 2 7 3 6 8 1 5 [43]: 4 2 7 3 6 8 5 1 [44]: 4 2 7 5 1 8 6 3 [45]: 4 2 8 5 7 1 3 6 [46]: 4 2 8 6 1 3 5 7 [47]: 5 7 1 3 8 6 4 2 [48]: 5 7 1 4 2 8 6 3 [49]: 5 7 2 4 8 1 3 6 [50]: 5 7 2 6 3 1 4 8 [51]: 5 7 2 6 3 1 8 4 [52]: 5 7 4 1 3 8 6 2 [53]: 5 8 4 1 3 6 2 7 [54]: 5 8 4 1 7 2 6 3 [55]: 5 1 4 6 8 2 7 3 [56]: 5 1 8 4 2 7 3 6 [57]: 5 1 8 6 3 7 2 4 [58]: 5 2 4 6 8 3 1 7 [59]: 5 2 4 7 3 8 6 1 [60]: 5 2 6 1 7 4 8 3 [61]: 5 2 8 1 4 7 3 6 [62]: 5 3 8 4 7 1 6 2 [63]: 5 3 1 6 8 2 4 7 [64]: 5 3 1 7 2 8 6 4 [65]: 6 8 2 4 1 7 5 3 [66]: 6 1 5 2 8 3 7 4 [67]: 6 2 7 1 3 5 8 4 [68]: 6 2 7 1 4 8 5 3 [69]: 6 3 5 7 1 4 2 8 [70]: 6 3 5 8 1 4 2 7 [71]: 6 3 7 2 4 8 1 5 [72]: 6 3 7 2 8 5 1 4 [73]: 6 3 7 4 1 8 2 5 [74]: 6 3 1 7 5 8 2 4 [75]: 6 3 1 8 4 2 7 5 [76]: 6 3 1 8 5 2 4 7 [77]: 6 4 7 1 3 5 2 8 [78]: 6 4 7 1 8 2 5 3 [79]: 6 4 1 5 8 2 7 3 [80]: 6 4 2 8 5 7 1 3 [81]: 7 1 3 8 6 4 2 5 [82]: 7 2 4 1 8 5 3 6 [83]: 7 2 6 3 1 4 8 5 [84]: 7 3 8 2 5 1 6 4 [85]: 7 3 1 6 8 5 2 4 [86]: 7 4 2 5 8 1 3 6 [87]: 7 4 2 8 6 1 3 5 [88]: 7 5 3 1 6 8 2 4 [89]: 8 2 4 1 7 5 3 6 [90]: 8 2 5 3 1 7 4 6 [91]: 8 3 1 6 2 5 7 4 [92]: 8 4 1 3 6 2 7 5。

c++八皇后问题最简单算法

c++八皇后问题最简单算法

八皇后问题是一个经典的回溯算法问题。

下面是一个使用C语言实现的简单算法:c复制代码#include<stdio.h>#include<stdbool.h>#define N 8int col[N] = {0}; // 表示皇后所在的列int queens[N][N] = {0}; // 存储棋盘状态bool is_valid(int row, int col) {for (int i = 0; i < row; i++) {if (queens[i][col] || queens[i][col - (row - i)] || queens[i][col + (row -i)]) {return false;}}return true;}void backtrack(int row) {if (row == N) { // 找到了一组解for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {printf("%d ", queens[i][j]);}printf("\n");}return;}for (int col = 0; col < N; col++) {if (is_valid(row, col)) { // 如果当前位置是合法的,则放置皇后queens[row][col] = 1;col[row] = col; // 记录每行皇后所在的列backtrack(row + 1); // 继续放下一行的皇后queens[row][col] = 0; // 回溯,撤销当前位置的皇后}}}int main() {backtrack(0); // 从第0行开始放皇后return0;}在上面的代码中,我们使用一个一维数组col来记录每一行皇后所在的列。

在is_valid函数中,我们检查当前位置是否合法,即与前面的皇后不冲突。

C++实现LeetCode(51.N皇后问题)

C++实现LeetCode(51.N皇后问题)

C++实现LeetCode(51.N皇后问题)[LeetCode] 51. N-Queens N皇后问题The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.Given an integer n, return all distinct solutions to the n-queens puzzle.Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.Example:Input: 4Output: [[".Q..", // Solution 1"...Q","Q...","..Q."],["..Q.", // Solution 2"Q...","...Q",".Q.."]]Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.经典的N皇后问题,基本所有的算法书中都会包含的问题。

可能有些⼈对国际象棋不太熟悉,⼤家都知道中国象棋中最叼的是车,横竖都能⾛,但是在国际象棋中还有更叼的,就是皇后,不但能横竖⾛,还能⾛两个斜线,有如 bug ⼀般的存在。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX 8
int board[MAX]; //皇后坐标数组,MAX为行数,board[MAX]为列数int sum=0;
int n;
struct node
{
int a[8][8];
}open[10000],closed[200];
void show_result()
{
int i;
for(i=0;i<MAX;i++)
printf("(%d,%d)",i,board[i]);
printf("\n");
sum++;
}
int check_cross(int n)
{
int i;
for(i=0;i<n;i++)
{
if(board[i]==board[n]||(n-i)==abs(board[i]-board[n]))
return 1;
}
return 0;
}
void put_chess(int n)
{
int i;
for(i=0;i<MAX;i++)
{
board[n]=i;
if(!check_cross(n))
{
if(n==MAX-1)
show_result();
else
put_chess(n+1);
}
}
}
void init(int num)
{
int i,j;
for(i=0;i<8;i++)
for(j=0;j<8;j++)
open[num].a[i][j]=0; }
int search(int num[8][8],int m,int n) {
int i,j;
for(i=0;i<8&&i!=m;i++)
{
if(num[i][n]==1)
return 1;
}
for(i=0;i<8&&i!=n;i++)
{
if(num[m][i]==1)
return 1;
}
i=m-1;
j=n+1;
while(i>=0&&j<8)
{
if(num[i][j]==1)
return 1;
i--;
j++;
}
i=m-1;
j=n-1;
while(i>=0&&j>=0)
{
if(num[i][j]==1)
return 1;
i--;
j--;
}
return 0;
}
main()
{
int m=0,n=0,head=0,tail=1,test,num=0,nnn=0;
init(head);
for(;m<8;m++)
{
for(;head<=num;head++)
{
for(;n<8;n++)
{
open[head].a[m][n]=1;
test=search(open[head].a,m,n);
if(test==1)
{
open[head].a[m][n]=0;
}
else
{
init(tail);
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
open[tail].a[i][j]=open[head].a[i][j];
tail++;
open[head].a[m][n]=0;
if(m==7)
{
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
closed[nnn].a[i][j]=open[tail].a[i][j];
nnn++;
}
}
}
}
num=tail-1;
}
printf("八皇后的各种情况如下,八皇后以(a,b)形式表示a代表第a+1行,b代表第b+1列:\n");
put_chess(0);
printf("共有%d种八皇后情况\n",sum);
getchar();
return 0;
}。

相关文档
最新文档