C语言八皇后问题程序设计
八皇后问题及解答
*(queenArray+countSum+1)=0;}else{
*(queenArray+countSum--)=0;
if(*(queenArray+countSum)<queenSum) ++*(queenArray+countSum);
placequeen
(0);
System.out.println("\n\n\n八皇后共有"+oktimes+"个解法made by yifi 2003");}
publicstaticvoidplacequeen(intnum){//num为现在要放置的行数inti=0;
booleanqsave[]=newboolean[QueenMax];
++*(queenArray+countSum);}continue;}}
else {
++*(queenArray+countSum);
continue;}}
queenPosition++;
for(printCount=1;printCount<=queenSum;printCount++)
printf("%3d%",*(queenArray+printCount));
posArray2[deep] = j;
deep++;
FindQuePos(posArray2,queen_num,deep);
deep--;
八皇后c语言课程设计
八皇后c语言课程设计一、课程目标知识目标:1. 学生能理解“八皇后”问题的背景和数学原理,掌握利用计算机程序解决问题的基本思路。
2. 学生能掌握C语言的基本控制结构,包括循环、选择和函数调用。
3. 学生能运用数组和逻辑判断解决排列组合问题,实现对八皇后问题的所有有效解的搜索。
技能目标:4. 学生能够运用C语言编写程序,实现八皇后问题的算法,并能够调试和优化代码。
5. 学生能够通过分析问题,设计出有效算法,培养逻辑思维能力和问题解决能力。
情感态度价值观目标:6. 学生通过解决八皇后问题,培养对计算机编程的兴趣和热情,增强对信息科学的认识。
7. 学生在学习过程中,培养团队合作意识和探究精神,提高面对复杂问题的耐心和毅力。
8. 学生能够认识到编程在解决实际问题中的应用价值,激发其在未来学习和工作中运用编程技术的积极性。
二、教学内容本课程将依据以下教学内容展开:1. C语言基础知识回顾:变量定义、数据类型、运算符、输入输出、控制结构(循环、选择)。
- 教材章节:第1章 C语言概述,第2章 数据类型与运算符,第3章 控制结构。
2. 数组的应用:一维数组的使用,理解数组在存储多数据时的优势。
- 教材章节:第4章 数组与字符串。
3. 函数的定义与调用:编写和调用自定义函数,理解模块化编程的重要性。
- 教材章节:第5章 函数。
4. 八皇后问题背景介绍:问题的起源、数学原理和解决思路。
- 教材章节:附录 或 课外拓展内容。
5. 八皇后算法设计:回溯法的基本原理,以及其在八皇后问题中的应用。
- 教材章节:算法设计与分析部分。
6. 编程实践:学生动手编写C语言程序解决八皇后问题,包括代码调试和优化。
- 教材章节:编程实践案例。
7. 算法优化:讨论如何提高程序的效率和减少计算时间,引入递归和剪枝的概念。
- 教材章节:算法优化部分。
教学内容将按照上述大纲逐步进行,确保学生能够系统地掌握C语言编程基础,并能将其应用于解决实际问题。
八皇后问题 C语言程序设计
八皇后问题学2012年 9 月 5 日目录一、选题1.1背景知识 (2)1.2设计目的与要求 (2)二、算法设计2.1问题分析 (3)2.2算法设计 (3)三、详细设计3.1源程序清单 (4)四、调试结果及分析4.1调试结果 (6)4.2调试分析 (7)五、课程设计总结5.1总结及体会 (7)六、答辩6.1答辩记录 (8)6.2教师意见 (8)一、选题及背景知识1.1 背景知识在国际象棋中,皇后是一个威力很大的棋子,她可以“横冲直撞”(在正负或垂直方向走任意步数),也可以“斜刺冲杀”(在正负45度方向走任意步数),所以在8*8的棋盘上要布互相不受攻击的皇后,最多只能布八个,共92种布法,再也不能有别的布法了——这就是著名的八皇后问题在8*8的国际象棋棋盘上,放置八个皇后,使得这八个棋子不能互相被对方吃掉。
也就是说一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子.因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。
1.2 设计要求要求:·判断在国际象棋中,能否在空棋盘上摆放8个皇后,并使其中任意两个皇后不能在同一行,同一列或同一对角线上。
·编写完整的摆放八皇后问题的程序·具体要求第一个皇后的起始位置由键盘输入二、算法设计2.1问题分析设计——图形表示下图中,Q代表皇后假设在第k列上找到合适的位置放置一个皇后,要求它与第1——k-1列上的皇后不同行、列、对角线;可以从图上找到规律:不同列时成立,皇后放在第k列上;讨论行时,第j个皇后的位置(a[j] ,j)要与(i,k)位置的皇后不同行;如果同在/斜线上,行列值之和相同;如果同在\斜线上,行列值之差相同;如果斜线不分方向则同一斜线上两皇后的行号之差的绝对值与列号之差的绝对值相同,可表示为(|a[j]-i|=|j-k|)。
2.2 算法设计利用计算机运行速度快的特点,采用枚举法,逐一尝试各种摆放方式,来判断最终摆法。
八皇后的递归和非递归的解法(C++)
八皇后的递归和非递归的解法(C++)八皇后的递归和非递归的解法(C++)//描述:用递归和非递归模拟n皇后问题//输入:问题的规模:n//输出:皇后放置的方法排列和总数#include<iostream>#include<iomanip>#include<cmath>#include<stack>using namespace std;//利用递归求解皇后问题 x[i]表示皇后放在第i行第x[i]列static int count;//判断如果皇后放在第i行,第j列是否与前面的皇后冲突bool place(int i,int j,int* path)//path存放路径{int row;for(row=0;row<i;row++){if(abs(row-i)==abs(path[row]-j))//在同一条斜线上return false;if(j==path[row])//在同一列return false;}return true;}//利用递归来求解,而且当row==0时,即求解全局的解//path[n]用来存放路径void queen(int row,int* path,int n)if(row==n){//输出结果,并将办法数加1for(int i=0;i<n;i++){cout<<setw(5)<<left<<path[i];}cout<<endl;count++;}else{int j;//表示当前列是否可行for(j=0;j<n;j++){//如果可行,则放置并且递归调用处理下一行if(place(row,j,path)){path[row]=j;//这里相当于入栈的过程queen(row+1,path,n);}}}}//利用迭代来求解void queen_another(int n,int* path) {int i=0;for(i=0;i<n;i++){int j=0;for(;j<n;j++){if(place(i,j,path)){path[i]=j;cout<<"row "<<i<<"col "<<j<<endl; break;}}//没有合适的位置,所以要回溯到上一个最合适的节点if(j==n){i--;while(i>=0){int k=path[i]+1;while(k<n&&!(place(i,k,path)))k++;if(k==n)i--;else{path[i]=k;break;}if(i<0){cout<<"there is no way "<<endl;return;}}}if(i==n)for(int j=0;j<n;j++){cout<<setw(5)<<left<<path[j];path[j]=-1000;}}//利用栈来模拟递归,在某个扩展节点出处,将所有符合条件的节点加入到里面struct pos{int row;int col;};//找到当前最合适的节点,如果没有找到则返回-1int find_col(int row,int col,int* path,int n){int j;for(j=col;j<n;j++){if(place(row,j,path))return j;if(j==n)return -1;}//利用栈来模拟八皇后问题void stack_stimu(int n,int* path){stack<struct pos> s;int currow=0;int flag=0;//主要结构分为两部分,第一按照正常顺序寻找节点//然后找出回溯的情况:在八皇后问题中主要有两中:1.到达结尾找出路径 2.当前行没有满足条件的位置while(true){if(currow<n){int col=find_col(currow,0,path,n);if(col!=-1){pos node;node.row=currow;node.col=col;s.push(node);path[currow]=col;currow++;}elseflag=1;}else{for(int i=0;i<n;i++)cout<<setw(5)<<left<<path[i];cout<<endl;count++;flag=1;}// 进行回溯if(flag==1){//描述了回溯的过程while(!s.empty()){pos temp=s.top();if(temp.col!=7){//查找当前最适合的节点,并入栈int j=find_col(temp.row,temp.col+1,path,n); if(j!=-1){pos node;node.row=temp.row;node.col=j;s.pop();s.push(node);path[temp.row]=j;currow=temp.row+1;flag=0;break;}elses.pop();}elses.pop();}if(s.empty())return;//函数的出口处}}//end for while(true)}int main(){cout<<"Queen Place Problem:"<<endl; cout<<"Input the value of n"<<endl; int n;cout<<" n>";cin>>n;int* path=new int[n];//初始化for(int i=0;i<n;i++)path[i]=-1000;//queen_another(n,path);//queen(0,path,n);stack_stimu(n,path);cout<<"the count is: "<<count<<endl; getchar();getchar(); return 0; }。
数据结构与程序设计12八皇后问题
Post: A queen has been inserted into the square at row count and column
col; count has been incremented by 1.
*/
{
queen_square[count++][col] = true;
}
7/25/2024
for (i = 0; ok && i < count; i++)
ok = !queen_square[i][col];
// Check upper part of column
for (i = 1; ok && count - i >= 0 && col - i >= 0; i++)
Байду номын сангаас
ok = !queen_square[count - i][col - i]; // Check upper-left diagonal
}
7/25/2024
数据结构与程序设计
11
Eight-Queens Puzzle p191
bool Queens::unguarded(int col) const
/*
Post: Returns true or false according as the square in the first
数据结构与程序设计
10
Eight-Queens Puzzle
Queens::Queens(int size)
/*
Post: The Queens object is set up as an empty
八皇后问题代码实现
八皇后问题代码实现/*代码解析*//* Code by Slyar */ #include <stdio.h>#include<stdlib.h> #define max 8 int queen[max], sum=0; /* max为棋盘最大坐标*/ void show() /* 输出所有皇后的坐标*/{ int i; for(i = 0; i < max; i++){ printf("(%d,%d) ", i, queen[i]); }printf("\n"); sum++;} int check(int n) /* 检查当前列能否放置皇后*/{ int i; for(i = 0; i < 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 < 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语言八皇后问题程序设计
2014年春季学期《C项目设计》报告题目:八皇后问题学号:092213112姓名:刘泽中组名:1指导教师:宋东兴日期:2014.05.15目录正文 (3)1.问题描述 (3)2. 总体设计与分析 (3)3. 相关代码 (5)4. 调试分析 (9)5.软件使用说明书 (11)总结 (11)附录:部分原程序代码 (12)一、问题描述1.八皇后问题:是一个古老而著名的问题。
该问题是十九世纪著名的数学家高斯1850年提出:在8×8棋盘上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法?2.解决八皇后问题的关键在于:(1)找到合理的数据结构存放棋子的摆放位置。
(2)要有合理的冲突检查算法。
采用的方法是,先把8个棋子摆在棋盘上,每行摆一个,然后去检查这种摆放是否有冲突,如果没有冲突,即找到了一种解决方案。
由于皇后的摆放位置不能通过某种公式来确定,因此对于每个皇后的摆放位置都要进行试探和纠正,这就是“回溯”的思想。
在8个皇后未放置完成前,每行摆放一个皇后,摆放第i个皇后和第i+1个皇后的试探方法是相同的,因此完全可以采用递归的方法来处理。
二、总体设计与分析1.设计效果画一个8*8的国际象棋盘,在棋盘某一位置上放一棋子,并让它按从左到右的方向自动运动,用户可以使用光标键调整棋子运动的方向,找出所有可能的摆放方案,将包含指定的棋子的(如3行4列)摆放方案找出并显示出来。
2.、总体设计程序总体分为两大块:(1)八皇后摆法的寻找;(2)棋盘及棋子的设计。
3、详细模块(1)八皇后摆法的寻找:int chess[8][8]={0}; //二维数组表示8*8棋盘,全部清0,(0代表该位没有放棋子)void queen(int i,int n){ //i表示从第i行起为后续棋子选择合适位置,n代表n*n棋盘if(i==n)output(n); //输出棋盘当前布局;else{for(j=0;j<n;j++){ //每行可能有n个摆放位置chess[i][j] = 1; //在第i行,j列上放一棋子if(!canAttack(i,j)) //如果当前布局合法,不受前i-1行的攻击queen(i+1,n); //递归摆放i+1行chess[i][j] = 0; //移走第i行,j列的棋子}}}int canAttack(int i,int j){ //判断0到i-1行已摆放的棋子,对[i,j]位置是否可以攻击for(m=0;m<i;m++){for(n=0;n<8;n++){if(chess[m][n]==1){if(m==i||n==j) return 1;if(m+n==i+j || m-n==i-j) return 1;}}}return 0;}void output(){ //输出一组解,即打印出8个皇后的坐标for(int i=0;i<8;i++){for(int j=0;j<8;j++){if(chess[i][j]==1){printf("(%d,%d)",i,j);}}}printf(“\n”);}int main(){queen(0,8);return 0;}(2)棋盘及棋子的设计:void drawBlock(int i,int j){ //棋盘的设计(每一个小方块)int x0,y0,x1,y1;x0=ORGX+j*W;y0=ORGY+i*H;x1=x0+W-1;y1=y0+H-1;setcolor(WHITE);rectangle(x0,y0,x1,y1);setfillstyle(1,LIGHTGRAY);floodfill(x0+1,y0+1,WHITE);setcolor(WHITE);line(x0,y0,x1,y0);line(x0,y0,x0,y1);setcolor(BLACK);line(x1,y0,x1,y1);line(x0,y1,x1,y1);}void drawBall(Ball ball){ //棋子的设计int x0,y0;x0=ball.startX+ball.c*ball.w+ball.w/2;y0=ball.startY+ball.r*ball.h+ball.h/2;setcolor(RED);setfillstyle(1,RED);fillellipse(x0,y0,10,10);}4.程序设计思路:先设计程序,找到八皇后的摆放位置,方法是:先把8个棋子摆在棋盘上,每行摆一个,然后去检查这种摆放是否有冲突,如果没有冲突,即找到了一种解决方案。
C语言程序设计 数组(8.3.12)--八皇后问题
其中,rowPos[i]表示第 i 行上皇后的位置(即位于第 i 行的第几列),col[j]表示第 j 列上没 有皇后占据,leftDiag[k]表示第 k 条左对角线(↙)上没有皇后占据,rightDiag[k]表示第 k 条右对角线(↘)上没有皇后占据。
4. 八皇后问题
【任务描述】八皇后问题是 1850 年由数学家 Gauss 首先提出的。问题是这样的:在一个 8×8 的国际象棋棋盘上放置 8 个皇后,要求每个皇后两两之间不“冲突”,即没有一个皇 后能“吃掉”任何其他一个皇后。简单地说,就是没有任何两个皇后占据棋盘上的同一行或 同一列或同一对角线,即在每一横行、竖列、斜线上都只有一个皇后。
在该位置放置皇后; if (i < 7) {
尝试第 i+1 种摆法; if (不成功)
移走该位置上的皇后; } else
置标志变量为成功; } } while (不成功 && 位置未试完); return 标志变量记录的成功与否信息; }
由于对角线有两个方向,在同一对角线上的所有点(设其坐标为(i, j)),要么行、列坐 标之和 i+j 是常数,要么行、列坐标之差 ij 是常数。其中,行、列坐标之和(在 0~14 范围 内)相等的诸方格在同一条(↙)对角线上,而行、列坐标之差(在7~7 范围内)相等 的诸方格在同一条↘对角线上。因此,可用 b[i+j]的值表示位置为(i, j)的(↙)对角线上是 否有皇后占据(若无皇后占据,则置 b[i+j]为真,否则置 b[i+j]为假),用 c[ij+7]表示位置 为(i, j)的(↘)对角线上是否有皇后占据(若 无皇后占据,则置 c[ij+7]为真,否则置 c[ij+7]为假)。如果 col[j],leftDiag[i+j]和 rightDiag[ij+7]都为真,则说明位置(i, j)是安全
八皇后问题C程序
6 八皇后问题【问题描述】在一个8×8的国际象棋棋盘上放置8个皇后,要求每个皇后两两之间不“冲突”,即没有一个皇后能“吃掉”任何其他一个皇后,简单的说就是没有任何两个皇后占据棋盘上的同一行或同一列或同一对角线,即在每一横列、竖列、斜列都只有一个皇后。
/*file name:Queen.cDescription:利用递归法求出8个皇后问题的解*/#include<stdio.h>#include<conio.h>#define TRUE 1#define FALSE 0#define MAXQUEEN 8#define ABS(x) ((x>0)?(x):-(x)) /*求x的绝对值*//*存放8个皇后的列位置,数组注标为皇后的列位置*/int queen[MAXQUEEN];int total_solution; /*计算共有几组解*//*函数原型声明*/void place(int);int attack(int,int);void output_solution();void main(){place(0); /*从第0个皇后开始摆放至棋盘*/getch();}void place(int q){C语言大学实用教程学习指导·268·int i=0;while(i<MAXQUEEN){if(!attack(i,q)) /*皇后未受攻击*/{queen[q]=i; /*储存皇后所在的列位置*//*判断是否找到一组解*/if(q==MAXQUEEN-1)output_solution(); /*列出此组解*/elseplace(q+1); /*否则继续摆下一个皇后*/}i++;}}/*测试在(row,col)上的皇后是否遭受攻击若遭受攻击则返回值为1,否则返回0*/int attack(int row,int col){int i,atk=FALSE;int offset_row,offset_col;i=0;while(!atk&&i<col){offset_col=ABS(i-col);offset_row=ABS(queen[i]-row);/*判断两皇后是否在同一列,是否在同一对角线*//*若两皇后在同列或同对角线,则产生攻击,atk==TRUE*/atk=(queen[i]==row)||(offset_row==offset_col);i++;}return atk;}/*列出8个皇后的解*/void output_solution()第3章学习指导·269·{int x,y;total_solution+=1;printf("Solution#%3d\n\t",total_solution);for(x=0;x<MAXQUEEN;x++){for(y=0;y<MAXQUEEN;y++)if(x==queen[y])printf("Q"); /*用字母Q表示皇后*/elseprintf("-"); /*用-表示空白*/printf("\n\t");}printf("\n");}。
c语言八皇后课程设计
c语言八皇后课程设计一、课程目标知识目标:1. 学生能理解“八皇后”问题的背景和数学原理,掌握利用C语言解决该问题的基本思路。
2. 学生能掌握并运用数组、循环、条件判断等C语言基本语法,实现八皇后问题的算法。
3. 学生能理解递归的概念,并掌握递归算法在解决八皇后问题中的应用。
技能目标:1. 学生能运用C语言编写程序,解决八皇后问题,并生成所有可能的解决方案。
2. 学生能够通过算法优化,提高程序运行效率,培养学生的编程思维和问题解决能力。
3. 学生能够利用所学知识,对八皇后问题进行拓展,如求解更大规模的N皇后问题。
情感态度价值观目标:1. 学生在解决八皇后问题的过程中,培养对编程和计算机科学的兴趣,提高学习积极性。
2. 学生通过团队协作、交流讨论,培养合作精神和沟通能力,增强解决问题的信心。
3. 学生能够认识到编程在解决实际问题中的应用价值,激发创新精神和实践能力。
课程性质:本课程设计属于C语言程序设计课程的一部分,旨在通过实际问题的解决,提高学生的编程能力和逻辑思维能力。
学生特点:学生处于高中年级,具备一定的C语言基础,对编程有一定兴趣,但编程实践能力和问题解决能力有待提高。
教学要求:教师应注重引导学生主动探索,鼓励学生进行算法优化,关注学生的个体差异,提供有针对性的指导,确保学生能够达到课程目标。
通过课程学习,使学生将所学知识转化为具体的学习成果,提高编程实践能力。
二、教学内容1. C语言基础知识回顾:数组的使用,循环结构(for、while),条件判断(if-else),函数的定义与调用。
2. 八皇后问题背景介绍:问题起源,数学原理,算法应用。
3. 八皇后问题算法分析:回溯法原理,递归与非递归实现,算法优化。
4. 编程实践:利用C语言实现八皇后问题的求解,生成所有解决方案,并讨论优化策略。
5. 拓展提高:引导学生探讨N皇后问题,比较不同规模问题的求解效率和算法适用性。
教学内容安排和进度:第一课时:C语言基础知识回顾,八皇后问题背景介绍。
八皇后源代码 原创 c语言实现
0 0 0 * 0 0 0 0
0 0 0 0 0 0 0 *
* 0 0 0 0 0 0 0
0 0 * 0 0 0 0 0
0 0 0 0 0 * 0 0
0 * 0 0 0 0 0 0
0 0 0 0 0 0 * 0
0 0 0 0 * 0 0 0
--------------------------
0 0 0 0 0 * 0 0
0 0 * 0 0 0 0 0
0 0 0 0 0 0 * 0
0 * 0 0 0 0 0 0
0 0 0 * 0 0 0 0
--------------------------
第5种
0 0 0 0 0 * 0 0
* 0 0 0 0 0 0 0
第20种
0 0 0 0 0 * 0 0
0 0 * 0 0 0 0 0
* 0 0 0 0 0 0 0
0 0 0 0 0 0 0 *
0 0 0 0 * 0 0 0
0 * 0 0 0 0 0 0
0 0 0 * 0 0 0 0
0 0 0 0 Biblioteka 0 * 0 --------------------------
第22种
0 0 0 0 0 0 0 *
0 0 0 * 0 0 0 0
* 0 0 0 0 0 0 0
0 0 * 0 0 0 0 0
0 0 0 0 0 * 0 0
0 * 0 0 0 0 0 0
0 0 0 0 0 0 * 0
0 0 0 0 * 0 0 0
--------------------------
八皇后问题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;}。
八皇后问题爬山法实现(C语言)
⼋皇后问题爬⼭法实现(C语⾔)运⾏环境VS20191 #include <stdio.h>2 #include <stdlib.h>3 #include <time.h>4 #include <stdbool.h>5//6// 编程题7// 爬⼭法(⼋皇后问题)8//91011//棋⼦结构体12//typedef struct Chess * Chess;1314int a[64];//a数组中记录了爬⼭过程中,每次棋盘碰撞次数的最⼩值15int array_count = 0; //array_count是a数组中的计数器16int number = 0;//number为爬⼭次数1718struct Global_Collidecount_min19 {20int mincollidecount[64]; //存放每次搜索后,棋盘上最⼩碰撞对数。
21int globalmin = -1;22 }global_collidecount_min;23242526 typedef struct27 {28int posx;29int posy;30int collidecount;31 }Coordinate;323334 typedef struct35 {36int value;//存储需要⽐较的数值37 Coordinate position[8];//存储棋盘上的坐标。
38 }Chess;3940 Chess chess;414243//地图结构体44 typedef struct45 {4647int map[8][8];48int collidecount[8][8];49int collidecount2[8][8];50int collidecount3[8][8];51 }Map;525354//C实现键值对(Map功能)55 typedef struct56 {57int key_x;58int key_y;59int value;60bool kaiguan;61 }Pair;6263646566 Pair pair[64];67 Map ditu;68697071// 初始化地图72void initmap()73 {77 ditu.map[x][y] = 0;78 ditu.collidecount[x][y] = 0;79 ditu.collidecount2[x][y] = 0;80 ditu.collidecount3[x][y] = 0;81 }82 }838485//初始化⼋皇后,按列赋初值86void initchess()87 {88int y;89for (y = 0; y < 8; y++)90 {91int x = rand() % 8;92 chess.value = 1;93 chess.position[y].posx = x;94 chess.position[y].posy = y;95 chess.position[y].collidecount = 0;96 ditu.map[x][y] = chess.value;//⽤1表⽰棋⼦97 }9899100 }101102103//初始化键值对104void initpair()105 {106107for (int i = 0; i < 63; i++)108 {109 pair[i].key_x = 0;110 pair[i].key_y = 0;111 pair[i].kaiguan = false;112 pair[i].value = 0;113 }114115 }116117118119120//输出地图121void outmap()122 {123124for (int x = 0; x < 8; x++)125 {126for (int y = 0; y < 8; y++)127 printf("%3.1d", ditu.map[x][y]);128 printf("\n");129 }130 }131132133//输出棋⼦位置134void outchess()135 {136137for (int x = 0; x < 8; x++)138 {139140 printf("x=%3.1d,y=%3.1d", chess.position[x].posx, chess.position[x].posy); 141 printf("\n");142 }143144 }145146147148void outmap1()149 {150151for (int x = 0; x < 8; x++)152 {153for (int y = 0; y < 8; y++)154 printf("%3.1d", ditu.collidecount[x][y]);155 printf("\n");156 }157 }158161 {162163for (int x = 0; x < 8; x++)164 {165for (int y = 0; y < 8; y++)166 printf("%3.1d", ditu.collidecount2[x][y]);167 printf("\n");168 }169 }170171172void outmap3()173 {174175for (int x = 0; x < 8; x++)176 {177for (int y = 0; y < 8; y++)178 printf("%3.1d", ditu.collidecount3[x][y]);179 printf("\n");180 }181 }182183184185// 将地图中的碰撞数ditu.collidecount,ditu.collidecount2,ditu.collidecount3置0;186void resetcollidecount()187 {188for (int x = 0; x < 8; x++)189for (int y = 0; y < 8; y++)190 {191 ditu.collidecount[x][y] = 0;192 ditu.collidecount2[x][y] = 0;193 ditu.collidecount3[x][y] = 0;194 }195 }196197198// 将存储棋盘中最⼩碰撞数的pair还原199void resetpair()200 {201202for (int i = 0; i < 63; i++)203 {204 pair[i].key_x = 0;205 pair[i].key_y = 0;206 pair[i].kaiguan = false;207 pair[i].value = 0;208 }209210 }211212213///<summary>214///将地图中的碰撞数ditu.collidecount,ditu.collidecount2,ditu.collidecount3置0;215///将存储棋盘中最⼩碰撞数的pair还原216///</summary>217void reset()218 {219 resetcollidecount();220 resetpair();221 }222223224225//查看是否与棋盘中皇后位置重复226int find(int row, int column)227 {228int m;229for (m = 0; m < 8; m++)230 {231int posx = chess.position[m].posx;232int posy = chess.position[m].posy;233if ((posx == row) && (posy == column))234return0;235 }236return1;237 }238239240241//随机选取⼀个最⼩碰撞数所在的位置,将地图中同列的皇后置0,242void randomselect(int position)245 srand((int)time(NULL));246int x = rand() % position;247/*printf("%d\t%d\n", x, position);248 printf("%d\n", pair[x].key_y);*/249int posx = chess.position[pair[x].key_y].posx;//取得同列皇后的横坐标250int posy = chess.position[pair[x].key_y].posy;//取得同列皇后的纵坐标251//printf("%d\t%d\n", posx, posy);252 chess.position[pair[x].key_y].posx = pair[x].key_x;//将皇后的横坐标该为最⼩碰撞数所在的位置的横坐标253//printf("%d\n", pair[x].key_x);254 ditu.map[posx][posy] = 0;//将地图中皇后原位置置0255 ditu.map[pair[x].key_x][pair[x].key_y] = 1;//将地图中皇后新位置置1256 }257258259//统计棋盘中最⼩碰撞数的个数,并将最⼩碰撞数所在位置和值存到pair键值对中260void countmin(int min)261 {262int position = 0;263for (int n = 0; n < 8; n++)264for (int m = 0; m < 8; m++)265if (ditu.collidecount3[n][m] == min)266 {267 pair[position].key_x = n;268 pair[position].key_y = m;269 pair[position].kaiguan = true;270 pair[position].value = min;271 position++;272 }273274 randomselect(position);275 }276277278279280//遍历 pair[]数组,找出最⼩碰撞数281int visit()282 {283284int min, min_x, min_y;285286for (min_x = 0; min_x < 8; min_x++)287 {288for (min_y = 0; min_y < 8; min_y++)289 {290if (find(min_x, min_y))291 {292 min = ditu.collidecount3[min_x][min_y];293//printf("%d\n", min);294//printf("%d\t%d\n", min_x, min_y);295break;296 }297 }298break;299 }300/*printf("%d\t%d\n", min_x, min_y);301 printf("%d\n", min);*/302303304for (int i = 0; i < 8; i++)305for (int j = 0; j < 8; j++)306if (find(i, j))307 {308if (min > ditu.collidecount3[i][j])309 min = ditu.collidecount3[i][j];310 }311//printf("%d\n", min);312313return min;314 }315316317318319320int countcollidecount()321 {322int row, column, count = 0;323for (row = 0; row < 8; row++)324for (column = 0; column < 8; column++)325if (ditu.collidecount2[row][column] != 0)326 count += ditu.collidecount2[row][column];329330331332///<summary>333///对m列的n位置上的棋⼦进⾏检测334///</summary>335///<param name="hang"></param>336///<param name="lie"></param>337void function3(int hang, int lie)338 {339int collidecount = 0;340int collidecount2 = 0;341//⾏检测342for (int count = 0; count < 8; count++)343 {344int m, n;345int posx = chess.position[count].posx;346int posy = chess.position[count].posy;347//printf("x=%d,y=%d\n", posx, posy);348for (m = 0; m < 8; m++)349 {350if ((ditu.map[posx][m] != 0) && (m != posy)) 351 {352 collidecount++;353354 }355else356continue;357 }358359360361362//lie列363for (n = 0; n < 8; n++)364 {365if ((ditu.map[n][posy] != 0) && (n != posx)) 366 {367 collidecount++;368 }369else370continue;371 }372373//dui'jiao'xian对⾓线374375 n = posx - 1; m = posy + 1;376 { for (; (n != -1) && (m != 8); n--, m++)377if (ditu.map[n][m] != 0)378 collidecount++;379 }380381 n = posx + 1; m = posy - 1;382 { for (; (n != 8) && (m != -1); n++, m--)383if (ditu.map[n][m] != 0)384 collidecount++;385 }386 n = posx - 1; m = posy - 1;387388 { for (; (n != -1) && (m != -1); n--, m--)389if (ditu.map[n][m] != 0)390 collidecount++;391 }392393 n = posx + 1; m = posy + 1;394 { for (; (n != 8) && (m != 8); n++, m++)395if (ditu.map[n][m] != 0)396 collidecount++;397 ditu.collidecount2[posx][posy] += collidecount; 398 } collidecount = 0;399400401402 }403404 ditu.collidecount3[hang][lie] = countcollidecount(); 405406407//置零408for (int n = 0; n < 8; n++)409 {410for (int m = 0; m < 8; m++)413 }414 }415416 }417418419420///<summary>421///检查同列中其他位置上的碰撞数422///</summary>423void function2()424 {425for (int n = 0; n < 8; n++)426for (int m = 0; m < 8; m++)427 {428429if (!find(n, m))430continue;431else432 {433int posx = chess.position[m].posx;434int posy = chess.position[m].posy;435 ditu.map[posx][posy] = 0;//将第m列的皇后置0 436 ditu.map[n][m] = 1;//将m列的第n个位置变为1 437 chess.position[m].posx = n;438 chess.position[m].posy = m;439 outmap();440 outmap3();441 function3(n, m);//对m列n位置碰撞检测442 printf("\n");443 ditu.map[posx][posy] = 1; //恢复皇后444 ditu.map[n][m] = 0;445 chess.position[m].posx = posx;446 chess.position[m].posy = posy;447 }448 }449450 }451452453454//碰撞对数检测455void function1()456 {457int collidecount = 0;458459//⾏检测460for (int count = 0; count < 8; count++)461 {462int m, n;463int posx = chess.position[count].posx;464int posy = chess.position[count].posy;465//printf("x=%d,y=%d\n", posx, posy);466for (m = 0; m < 8; m++)467 {468if ((ditu.map[posx][m] != 0) && (m != posy)) 469 {470 collidecount++;471472 }473else474continue;475 }476477478479//lie列480for (n = 0; n < 8; n++)481 {482if ((ditu.map[n][posy] != 0) && (n != posx))483 {484 collidecount++;485 }486else487continue;488 }489490//对⾓线检测491 n = posx - 1; m = posy + 1;492 { for (; (n != -1) && (m != 8); n--, m++)493if (ditu.map[n][m] != 0)494 collidecount++;497 n = posx + 1; m = posy - 1;498 { for (; (n != 8) && (m != -1); n++, m--)499if (ditu.map[n][m] != 0)500 collidecount++;501 }502 n = posx - 1; m = posy - 1;503504 { for (; (n != -1) && (m != -1); n--, m--)505if (ditu.map[n][m] != 0)506 collidecount++;507 }508509 n = posx + 1; m = posy + 1;510 { for (; (n != 8) && (m != 8); n++, m++)511if (ditu.map[n][m] != 0)512 collidecount++;513 chess.position[count].collidecount += collidecount;514 } collidecount = 0;515516 }517for (int count = 0; count < 8; count++)518 {519int posx = chess.position[count].posx;520int posy = chess.position[count].posy;521 ditu.map[posx][posy] = chess.position[count].collidecount;522 }523524 }525526527528529530//输出数组531void output(int* array)532 {533for (int i = 0; i <= 63; i++)534 {535 printf("%4.1d", array[i]);536 }537 }538539540void output_globalcollidecount()541 {542for (int i = 0; i <= 63; i++)543 { //if(global_collidecount_min.mincollidecount[i]!=-1)544 printf("%4.1d", global_collidecount_min.mincollidecount[i]);545 }546547 }548549550551//初始化碰撞数552void init_globalcollidecount()553 {554for (int i = 0; i <= 63; i++)555 {556 global_collidecount_min.mincollidecount[i] = -1;557 }558 }559560561562563564//存储棋盘中除皇后位置之外,最⼩的碰撞数565void save_mincollidecount(int global_min)566 {567if (global_collidecount_min.globalmin == -1)568 {569 global_collidecount_min.globalmin = global_min;570 global_collidecount_min.mincollidecount[0] = global_min;571 }572else573 {574575 global_collidecount_min.mincollidecount[number] == global_min; 576577578581 }582 }583584585586//如果碰撞数不⼩于之前所有棋盘检测的最⼩碰撞数,返回0,爬⼭法终⽌587int find_global_collidecount(int global)588 {589590591//global是第⼀次存⼊,或者global⽐global_collidecount_min.globalmin还⼩592if ((global_collidecount_min.globalmin == -1) || (global < global_collidecount_min.globalmin))593 {594 a[array_count++] = global;595 save_mincollidecount(global);596return1;597 }598else599return0;600 }601602603604605void HillClimbing()606 {607int min;608 initmap(); //初始化地图609 initpair(); //初始化键值对610 srand((int)time(NULL)); //随机种⼦611 initchess(); //初始化棋盘612 function1(); //碰撞对数检测613 function2(); //对除皇后外的其他位置进⾏碰撞检测,将检测值存于ditu.collidecount3614 min = visit(); //找出ditu.collidecount3中,皇后之外区域内的最⼩碰撞数615616617while (find_global_collidecount(min))//如果碰撞数不⼩于之前所有棋盘检测的最⼩碰撞数,返回0,爬⼭法终⽌618 {619 number++;620 countmin(min); //统计棋盘中最⼩碰撞数的个数,并将最⼩碰撞数所在位置和值存到pair键值对中621 reset(); //将地图中的碰撞数ditu.collidecount,ditu.collidecount2,ditu.collidecount3置0;将存储棋盘中最⼩碰撞数的pair[]还原(置0) 622 function1(); //碰撞对数检测623 function2(); // 检查同列中其他位置上的碰撞数624 min = visit(); //遍历 pair[]数组,找出最⼩碰撞数625 }626 }627628629630int main()631 {632 init_globalcollidecount();//初始化碰撞数633 HillClimbing();//爬⼭法634 printf("\n");635 printf("globalmin=%3.1d\n", global_collidecount_min.globalmin);//输出最终的最⼩碰撞次数636 output(a);//a数组中记录了爬⼭过程中,每次棋盘碰撞次数的最⼩值637 printf("\n");638 printf("%d", number);//number为爬⼭次数639return0;640 }。
八皇后问题的实现C语言
八皇后问题的实现(C语言)#include <stdio.h>#define N 8 // 定义棋盘的格数, 通过改变,也可以是4皇后, 16皇后, 9皇后什么的.int chess[N][N] = {0}; // 棋盘int count = 0; // 有多少种放法int canput(int row, int col) // 确定某一格能不能放{int i,j;for(i = 0; i < N; i ++){if(chess[i][col] == 1) //有同列的{return 0;}for(j = 0; j < N; j++){if(chess[row][j]==1) //有同行的{return 0;}if(((i-row)==(j-col)||(i-row)==(col-j))&&chess[i][j]==1) // 对角线上有的{return 0;}}}return 1;}void print_chess() // 打印放置的方案{int i, j;for(i = 0; i < N; i++){for(j = 0; j < N; j++){printf("%d ", chess[i][j]);}printf("\n");}printf("\n");}int put(int row) // 放置棋子, row是从哪一行开始, 通常是0 {int j, s;for(j = 0; j < N; j++) // 此一行的每一个格子都要试试能不能放{if(canput(row, j)) // 假如这格能放的话{chess[row][j] = 1; // 放置if(row == N-1) // 已经到了最后一行, 那么肯定成功****************************************************** {count = count +1;print_chess();chess[row][j] = 0; //成功后, 寻找下一种方法continue;}s = put(row+1); // 放置下一行的if(s == 0) // 假如下一行不能放{chess[row][j] = 0; // 那么这格是放错了的, 清除continue; // 找本行的下一个方格}else{break;}}}if(j==N) // 如果这一行的每个空格都不能放置{return 0; // 那么本行放置失败}else{return 1; // 本行放置成功}}int main(){int s ;s = put(0); // 放置printf("the number of put way is %d\n", count); //打印信息return 0;}。
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复制代码#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函数中,我们检查当前位置是否合法,即与前面的皇后不冲突。
八皇后问题实验报告递归非递归javaC语言+分析2
数据结构课程设计题目:八皇后问题指导教师:胡*学生院系:数学学院学生班级:信计*班学生姓名:黎*文学生学号: **********2016年12月30日目录一.功能以及需求分析 (3)1.1 问题的由来和背景 (3)1.2 问题的基本解决思路 (3)1.3 问题的应用 (3)二.总体设计 (4)2.1 运行环境 (4)2.2 程序框架 (4)2.3 算法分析 (4)2.3.1 总体算法分析 (4)2.3.2 非递归算法分析 (6)2.3.3 递归算法的分析 (6)三.详细设计 (6)3.1 递归法的详细设计 (6)3.2 非递归法的详细设计 (8)四.具体实现及运行 (10)4.1 QueenMainl类的实现: (10)4.2 QueenNR类: (10)4.3 QueenRS类: (11)4.4 C语言程序: (11)五. 总结 (12)六.代码清单 (13)6.1 Java代码: (13)6.2 C语言源代码: (20)一.功能以及需求分析1.1 问题的由来和背景八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。
该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
高斯认为有76种方案。
1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
计算机发明后,有多种计算机语言可以解决此问题。
八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。
八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。
当且仅当 n = 1 或 n ≥ 4 时问题有解。
八皇后 程序--完整代码,已测试
#include<conio.h>#include<iostream>using namespace std;//首先要求皇后不冲突,那么每行只应该有一个皇后//用queens[]数组存储每个皇后的位置//例如:queens[m]=n表示第m行的皇后放在第n列上#define MAX 8int sum=0;class QueenPuzzle{int queens[MAX]; //存储每行皇后的列标public:void printOut();//打印结果int IsValid(int n);//判断第n个皇后放上去以后,是否合法};void QueenPuzzle::printOut(){for(int i=0;i<MAX;i++){for(int j=0;j<MAX;j++){if(j==queens[i])cout<<"Q ";elsecout<<"o ";void placeQueen(int i); //递归算法放置皇后}cout<<endl;}cout<<endl<<"按q键盘退出,按其他键继续!"<<endl<<endl;if(getch()=='q')exit(0);}//在第i行放置皇后void QueenPuzzle::placeQueen(int i){for(int j=0;j<MAX;j++){//如果全部放完了输出结果if(i==MAX){sum++;cout<<"第"<<sum<<"组解:"<<endl;printOut();return;}}//放置皇后queens[i]=j;//此位置不能放皇后继续试验下一位置if(IsValid(i))placeQueen(i+1);}//判断第n个皇后放上去以后,是否合法,既是否无冲突int QueenPuzzle::IsValid(int n){//将第n个皇后的位置依次与前面n-1个皇后的位置比较for(int i=0;i<n;i++){//两个皇后在同一列上,返回0if(queens[i]==queens[n])return 0;//两个皇后在同一对角线上,返回0 if(abs(queens[i]-queens[n])==(n-i)) return 0;}//没有冲突,返回1return 1;}intmain(){}QueenPuzzle queen; queen.placeQueen(0);cout<<"共"<<sum<<"组解"<<endl; return 0;运行测试结果:……………………………………………………………。
八皇后问题(C语言版)
#include <stdio.h>#include "windows.h"#include<conio.h>#include <stdlib.h>#include <windows.h>// 添加下边这一行#include<conio.h>/* conio 是Console Input/Output (控制台输入输出)的简写,* 其中定义了通过控制台进行数据输入和数据输出的函数,* 主要是一些用户通过按键盘产生的对应操作,比如getch() 函数等等。
*/static char Queen[8][8];static int a[8];static int b[15];static int c[15];static int iQueenNum=0; // 记录总的棋盘状态数void qu(int i); // 参数i 代表行int main(){int iLine,iColumn;// 棋盘初始化,空格为* ,放置皇后的地方为@for(iLine=0;iLine<8;iLine++){a[iLine]=0; // 列标记初始化,表示无列冲突for(iColumn=0;iColumn<8;iColumn++)Queen[iLine][iColumn]='*';}// 主、从对角线标记初始化,表示没有冲突for(iLine=0;iLine<15;iLine++)b[iLine]=c[iLine]=0;qu(0);system("pause");return 0;}void qu(int i){int iColumn;for(iColumn=0;iColumn<8;iColumn++){ if(a[iColumn]==0&&b[i-iColumn+7]==0&&c[i+iColumn]==0) // 无冲突{如果Queen[i][iColumn]='@'; // 放皇后a[iColumn]=1; // 标记,下一次该列上不能放皇后b[i-iColumn+7]=1; // 标记,下一次该主对角线上不能放皇后c[i+iColumn]=1; // 标记,下一次该从对角线上不能放皇后if(i<7)qu(i+1); // 如果行还没有遍历完,进入下一行else // 否则输出{// 输出棋盘状态int iLine,iColumn;printf(" 第%d 种状态为:\n",++iQueenNum);for(iLine=0;iLine<8;iLine++){for(iColumn=0;iColumn<8;iColumn++)printf("%c ",Queen[iLine][iColumn]);printf("\n");}printf("\n\n");if(iQueenNum % 10 == 0){getch();}}// 如果前次的皇后放置导致后面的放置无论如何都不能满足要// 求,则回溯,重置Queen[i][iColumn]='*';a[iColumn]=0;b[i-iColumn+7]=0;c[i+iColumn]=0;}}}/*输出效果:第1 种状态为:* * @ * **第2 种状态为:第3 种状态为:* ******第4 种状态为:第5 种状态为:第6 种状态为:* /^∖ ************ * @ * * * * * * ** * @ * ** * * * * * * ** * @ * * *** @ * * * * * @** * * 第 7 种状态为* @ * * ** * * * * * *@ * * * * * * * ** @ * * * * @ ** * * @ * * * ** * * * * * * ** * @ * * *** @ * * * * @ * ** * *第 8 种状态为* @ * * ** * * * * *** @ * * @ * * * ** * * * * * * ** @ * * * * @ ** * * * * * * ** * @* * @ * ** * * * * * *@ * * *第 9 种状态为: * * * * @************第 10 种状态为: */@ * * * * *@* * * *。
八皇后问题实验报告源程序
八皇后问题实验报告源程序八皇后问题实验报告需求分析八皇后问题是一个古老而著名的问题。
该问题是十九世纪著名的数学家高斯1850年提出的。
八皇后问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子,问有多少种不同的摆法?并找出所有的摆法。
因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。
而本课程设计本人的目的也是通过C语言平台将一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现.最终将其问题变得一目了然,更加易懂。
概要分析本课件学生是用递归来实现的,分别一一测试了每一种摆法,并把它拥有的92种变化表现出来。
在这个程序中,学生的主要思路以及思想是这样的:1.解决冲突问题:这个问题包括了行,列,两条对角线;列:规定每一列放一个皇后,不会造成列上的冲突;行:当第i行被某个皇后占领后,则同一行上的所有空格都不能再放皇后,要把以i为下标的标记置为被占领状态;对角线:对角线有两个方向。
在这学生把这两条对角线称为:主对角线和从对角线。
在同一对角线上的所有点(设下标为(i,j)),要么(i+j)是常数,要么(i-j)是常数。
因此,当第i个皇后占领了第j列后,要同时把以(i+j)、(i-j)为下标的标记置为被占领状态。
(1) 满足上述条件的八个皇后,必然是每行一个,每列一个。
(2) 棋盘上任意一行、任意一列、任意一条斜线上都不能有两个皇后。
如果我们把8×8 的棋盘看成是一个平面直角坐标系,则八皇后问题就可以用数学语言来描述了,任意两个皇后在平面上的坐标应该同时满足以下三个条件:①两个皇后不在同一行:两个皇后的横坐标不相等;②两个皇后不在同一列:两个皇后的纵坐标不相等;③两个皇后不在同一条斜线上:两个皇后的横坐标之差的绝对值不等于两个皇后的纵坐标之差的绝对值。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
output(n); //输出棋盘当前布局;
else{
for(j=0;j<n;j++){
//每行可能有 n 个摆放位置
chess[i][j] = 1;
//在第 i 行,j 列上放一棋子
if(!canAttack(i,j)) //如果当前布局合法,不受前 i-1 行的攻击
queen(i+1,n); //递归摆放 i+1 行
二、总体设计与分析
1.设计效果 画一个 8*8 的国际象棋盘,在棋盘某一位置上放一棋子,并让它按从左
到右的方向自动运动,用户可以使用光标键调整棋子运动的方向,找出所有 可能的摆放方案,将包含指定的棋子的(如 3 行 4 列)摆放方案找出并显示 出来。。 2.、总体设计 程序总体分为两大块:(1)八皇后摆法的寻找;
(2)棋盘及棋子的设计。
3、详细模块
(1)八皇后摆法的寻找:
int chess[8][8]={0}; //二维数组表示 8*8 棋盘,全部清 0(, 0 代表该位没有
放棋子)
void queen(int i,int n){ //i 表示从第 i 行起为后续棋子选择合适位置,n 代
表 n*n 棋盘
if(i==n)
setcolor(WHITE); //增加立体感,设置白色
line(x0,y0,x1,y0);
line(x0,y0,x0,y1);
setcolor(BLACK);
line(x1,y0,x1,y1);
line(x0,y1,x1,y1);
}
5. void drawBall(Ball ball){ //画棋子
4.程序设计思路: 先设计程序,找到八皇后的摆放位置,方法是:先把 8 个棋子摆在棋盘上,
每行摆一个,然后去检查这种摆放是否有冲突,如果没有冲突,即找到了一种解 决方案。采用递归方法和“回溯”思想,找到 8*8 棋盘上的各种摆法,并把它打 印显示出来,共 92 种。
然后用 TC 进行图形编程,画出精美的棋盘,设计好棋子,从显示棋盘,显 示棋子,上下左右移动棋子,一步一步,减少错误率。
if(m==i||n==j) return 1;
if(m+n==i+j || m-n==i-j) return 1;
}
}
}
return 0;
}
void output(){
//输出一组解,即打印出 8 个皇后的坐标
for(int i=0;i<8;i++){
for(int j=0;j<8;j++){
if(chess[i][j]==1){
printf("(%d,%d)",i,j);
}
}
}
printf(“\n”);
}
int main(){
queen(0,8);
return 0;
}
(2)棋盘及棋子的设计: void drawBlock(int i,int j){ //棋盘的设计(每一个小方块) int x0,y0,x1,y1; x0=ORGX+j*W; y0=ORGY+i*H; x1=x0+W-1; y1=y0+H-1; setcolor(WHITE); rectangle(x0,y0,x1,y1); setfillstyle(1,LIGHTGRAY); floodfill(x0+1,y0+1,WHITE); setcolor(WHITE);
最后,将棋盘棋子和八皇后摆放的代码结合一起,做出可以使用光标键调整 棋子运动 方向,找出所有可能的摆放方案,将包含指定的棋子的(如 3 行 4 列)摆放方案 找出并显示出来的效果。 整个大程序看起来很复杂,但是把其分成二大块,最后再合成,便显得很容 易多了。
三、相关代码
1. typedef struct{ //定义一个棋子数据结构
}
}
size=imagesize(50,50,50+7*W+W-1,50+7*H+H-1); //计算大小,保存
到缓存区
buff1=(void *)malloc(size);
getimage(50,50,50+7*W+W-1,50+7*H+H-1,buff1); //将整个棋盘保
存的缓存区
}
4. void drawBlock(int i,int j){ //参数代表小方块在棋盘上的第 i 行,
}
}
}
if(fam==0){
//判断是否为全部输出,fam 为 1 时输出全部 92 种解
} } return 0; }
13. void outputa(){
Ball myBall;
int i,j,a=0,b=0;
for(i=0;i<8;i++){ //输出一组解,坐标分别保存到两个数组里
for(j=0;j<8;j++){
if(chess[i][j]==1){
fa[a++]=i;
fb[b++]=j;
initgraph(&gdriver,&gmode,"c:\\tc30\\bgi");
cleardevice();
}
3. void drawTable(){ //画棋盘
int i,j,size;
for(i=0;i<ROW;i++){
for(j=0;j<COL;j++){
drawBlock(i,j); //画小方块
}
6. void move(Ball *ball,int rols,int cols){ //棋子移动
switch(ball->dir){
case KEY_UP:ball->r--;;if(ball->r<0)
ball->r =
rols-1;break;
case KEY_DOWN:ball->r++;if(ball->r==rols) ball->r=0;break;
line(x0,y0,x1,y0); line(x0,y0,x0,y1); setcolor(BLACK); line(x1,y0,x1,y1); line(x0,y1,x1,y1); } void drawBall(Ball ball){ //棋子的设计
int x0,y0; x0=ball.startX+ball.c*ball.w+ball.w/2; y0=ball.startY+ball.r*ball.h+ball.h/2; setcolor(RED); setfillstyle(1,RED); fillellipse(x0,y0,10,10); }
总结··································································· 11 附录:部分原程序代码··········································· 12
一、 问题描述
1. 八皇后问题: 是一个古老而著名的问题。该问题是十九世纪著名的数学家高斯 1850 年提
int x0,y0;
x0=ball.startX+ball.c*ball.w+ball.w/2; //计算圆心坐标
y0=ball.startY+ball.r*ball.h+ball.h/2;
setcolor(RED);
setfillstyle(1,RED);
fillellipse(x0,y0,10,10);
case KEY_LEFT:ball->c--;if(ball->c<0) ball->c =
cols-1;break;
case KEY_RIGHT:ball->c++;if(ball->c==cols) ball->c=0;break; } } 7. void init2(Ball*ball,int r,int c,int size,int x0,int y0){ //初始化 一个棋子 ball->r=r; ball->c=c; ball->h=ball->w=size; ball->startX=x0; ball->startY=y0; } 8. void clearBall(){ //将缓存区的棋盘拿出来
} } } 12. int canAttack(int i,int j){// 判断 0 到 i-1 行已摆放的棋子,
对[i,j]位置是否可以攻击 int m,n; for(m=0;m<i;m++){
for(n=0;n<8;n++){ if(chess[m][n]==1){ if(m==i||n==j) return 1; if(m+n==i+j||m-n==i-j) return 1; }
putimage(50,50,buff1,COPY_PUT); } 9. void changeDir(Ball *ball,enum Direction dir){ //运动方向
ball->dir=dir; } 10. void fun(Ball ball){ //当前棋子的坐标
xx=ball.r; xy=ball.c; } 11. void queen(int i){ // i 表示从第 i 行起为后续棋子选择合适位置 int j; if(i==8)
int r,c;
//棋子在棋盘上的的行,列坐标