八皇后问题(C语言版)
八皇后问题(经典算法-回溯法)
⼋皇后问题(经典算法-回溯法)问题描述:⼋皇后问题(eight queens problem)是⼗九世纪著名的数学家⾼斯于1850年提出的。
问题是:在8×8的棋盘上摆放⼋个皇后,使其不能互相攻击。
即任意两个皇后都不能处于同⼀⾏、同⼀列或同⼀斜线上。
可以把⼋皇后问题扩展到n皇后问题,即在n×n的棋盘上摆放n个皇后,使任意两个皇后都不能互相攻击。
思路:使⽤回溯法依次假设皇后的位置,当第⼀个皇后确定后,寻找下⼀⾏的皇后位置,当满⾜左上、右上和正上⽅向⽆皇后,即矩阵中对应位置都为0,则可以确定皇后位置,依次判断下⼀⾏的皇后位置。
当到达第8⾏时,说明⼋个皇后安置完毕。
代码如下:#include<iostream>using namespace std;#define N 8int a[N][N];int count=0;//判断是否可放bool search(int r,int c){int i,j;//左上+正上for(i=r,j=c; i>=0 && j>=0; i--,j--){if(a[i][j] || a[i][c]){return false;}}//右上for(i=r,j=c; i>=0 && j<N; i--,j++){if(a[i][j]){return false;}}return true;}//输出void print(){for(int i=0;i<N;i++){for(int j=0;j<N;j++){cout<<a[i][j]<<" ";}cout<<endl;}}//回溯法查找适合的放法void queen(int r){if(r == 8){count++;cout<<"第"<<count<<"种放法\n";print();cout<<endl;return;}int i;for(i=0; i<N; i++){if(search(r,i)){a[r][i] = 1;queen(r+1);a[r][i] = 0;}}}//⼊⼝int main(){queen(0);cout<<"⼀共有"<<count<<"放法\n"; return 0;}。
八皇后问题MIPS实现方案
实验结果截图:
#store the result in $s0
#print and exit li $v0,1 move $a0,$s0 syscall li $v0,10 syscall #Function Queen Queen: addi $sp,$sp,-24 sw $ra,20($sp) sw $v0,16($sp) sw $a1,12($sp) sw $a2,8($sp) sw $s3,4($sp) addi $s7,$0,1 #initial $s7 which is i sw $s7,0($sp) #refresh and save i bne $a0,$a1,qLoop #n==QUEENS addi $a2,$a2,1#iCount=iCount+1 sw $a2,8($sp) #refresh and save iCount j qExit qLoop: lw $a1,12($sp) #load n to $a1 sll $t0,$a1,2 #$t0=4*n add $s3,$t0,$gp #$s3 is the address of site[n] sw $s7,0($s3) #site[n]=i #let Valid to judge jal Valid beqz $v1,else #Valid==1 addi $a1,$a1,1#n=n+1 jal Queen move $a2,$v0 #put the result into $a2 sw $a2,8($sp) #refresh and save $a2 #Valid==0 else: lw $s7,0($sp) #load the previous i ##### addi $s7,$s7,1 #i=i+1 sw $s7,0($sp) #refresh and save i
八皇后问题
八皇后问题编辑八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。
该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
高斯认为有76种方案。
1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
计算机发明后,有多种方法可以解决此问题。
八皇后问题最早是由国际西洋棋棋手马克斯·贝瑟尔于1848年提出。
之后陆续有数学家对其进行研究,其中包括高斯和康托,并且将其推广为更一般的n皇后摆放问题。
八皇后问题的第一个解是在1850年由弗朗兹·诺克给出的。
诺克也是首先将问题推广到更一般的n皇后摆放问题的人之一。
1874年,S.冈德尔提出了一个通过行列式来求解的方法,这个方法后来又被J.W.L.格莱舍加以改进。
艾兹格·迪杰斯特拉在1972年用这个问题为例来说明他所谓结构性编程的能力。
八皇后问题在1990年代初期的著名电子游戏第七访客和NDS平台的著名电子游戏雷顿教授与不可思议的小镇中都有出现。
2名词解释算法介绍八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。
八皇后问题可以推广为更一般的n 皇后摆放问题:这时棋盘的大小变为n ×n ,而皇后个数也变成n 。
当且仅当 n = 1 或 n ≥ 4时问题有解。
C 语言1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 intn=8;intx[9];intnum = 0;//解的个数//判断第k 个皇后能否放在第x[k]列boolPlace(intk){inti = 1;while ( i < k){if ( x[i]==x[k] || (abs (x[i]-x[k]) ==abs (i-k)) )returnfalse ;i++;}returntrue ;}void nQueens(intn){x[0] = x[1] =0;intk=1;while (k > 0){x[k]+=1;//转到下一行while (x[k]<=n && Place(k)==false ){//如果无解,最后一个皇后就会安排到格子外面去 x[k]+=1;}if (x[k]<=n){//第k 个皇后仍被放置在格子内,有解if (k==n){num++;cout << num <<":\t";for (inti=1; i<=n; i++){28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 cout << x[i] <<"\t";}cout << endl;}else {k++;x[k]=0;//转到下一行}}else //第k 个皇后已经被放置到格子外了,没解,回溯k--;//回溯}}int_tmain(intargc, _TCHAR* argv[]){nQueens(n);getchar ();return 0;}Java 算法1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 publicclass Queen {// 同栏是否有皇后,1表示有privateint [] column;// 右上至左下是否有皇后privateint [] rup;// 左上至右下是否有皇后privateint [] lup;// 解答privateint [] queen;// 解答编号privateint num;public Queen() {column =newint [8+1];rup =newint [2*8+1];lup =newint [2*8+1];for (int i =1; i <=8; i++)column[i] =1;2223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 for(int i =1; i <=2*8; i++)rup[i] = lup[i] =1;queen =newint[8+1];}publicvoid backtrack(int i) {if(i >8) {showAnswer();}else{for(int j =1; j <=8; j++) {if(column[j] ==1&&rup[i+j] ==1&&lup[i-j+8] ==1) {queen[i] = j;// 设定为占用column[j] = rup[i+j] = lup[i-j+8] =0; backtrack(i+1);column[j] = rup[i+j] = lup[i-j+8] =1; }}}}protectedvoid showAnswer() {num++;System.out.println("\n解答 "+ num);for(int y =1; y <=8; y++) {for(int x =1; x <=8; x++) {if(queen[y] == x) {System.out.print(" Q");}else{System.out.print(" .");}}System.out.println();}}publicstaticvoid main(String[] args) {Queen queen =new Queen();queen.backtrack(1);66 67 }}Erlang 算法-module(queen).-export([printf/0,attack_range/2]).-define(MaxQueen, 4).%寻找字符串所有可能的排列%perms([]) ->%[[]];%perms(L) ->% [[H | T] || H <- L, T <-perms(L -- [H])].perms([]) ->[[]];perms(L)->[[H | T] || H <- L, T <- perms(L -- [H]),attack_range(H,T) == []].printf() ->L =lists:seq(1, ?MaxQueen),io:format("~p~n",[?MaxQueen]),perms(L).%检测出第一行的数字攻击到之后各行哪些数字%left 向下行的左侧检测%right 向下行的右侧检测attack_range(Queen,List) ->attack_range(Queen,left, List) ++ attack_range(Queen,right, List).attack_range(_, _, [])->[];attack_range(Queen, left, [H | _]) whenQueen - 1 =:= H ->[H];attack_range(Queen,right, [H | _]) when Queen + 1 =:= H->[H];attack_range(Queen, left, [_ | T])->attack_range(Queen - 1, left,T);attack_range(Queen, right, [_ | T])->attack_range(Queen + 1, right, T).C 语言算法C 代码头文件1 2 3 4 5 6 7 8 9 10 11 //eigqueprob.h#include#define N 8 /* N 表示皇后的个数 *//* 用来定义答案的结构体*/typedefstruct {intline;/* 答案的行号 */introw;/* 答案的列号 */}ANSWER_TYPE;/* 用来定义某个位置是否被占用 */12 13 14 15 16 17 18 19 20 typedefenum {notoccued = 0,/* 没被占用 */occued = 1/* 被占用 */}IFOCCUED; /* 该列是否已经有其他皇后占用 */IFOCCUED rowoccu[N];/* 左上-右下对角位置已经有其他皇后占用 */IFOCCUED LeftTop_RightDown[2*N-1];/* 右上-左下对角位置已经有其他皇后占用*/IFOCCUED RightTop_LefttDown[2*N-1];/* 最后的答案记录 */ANSWER_TYPE answer[N];主程序1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include "eigqueprob.h"/* 寻找下一行占用的位置 */void nextline(intLineIndex){static asnnum = 0;/* 统计答案的个数 */intRowIndex = 0;/* 列索引 */intPrintIndex = 0;/* 按列开始遍历 */for (RowIndex=0;RowIndex{/* 如果列和两个对角线上都没有被占用的话,则占用该位置 */if ((notoccued == rowoccu[RowIndex])\&&(notoccued == LeftTop_RightDown[LineIndex-RowIndex+N-1])\&&(notoccued == RightTop_LefttDown[LineIndex+RowIndex])){/* 标记已占用 */rowoccu[RowIndex] = occued;LeftTop_RightDown[LineIndex-RowIndex+N-1] = occued;RightTop_LefttDown[LineIndex+RowIndex] = occued;/* 标记被占用的行、列号 */answer[LineIndex].line = LineIndex;answer[LineIndex].row = RowIndex;/* 如果不是最后一行,继续找下一行可以占用的位置 */if ((N-1) > LineIndex ){nextline(LineIndex+1);}/* 如果已经到了最后一行,输出结果 */else{asnnum++;printf ("\nThe %dth answer is :",asnnum);for (PrintIndex=0;PrintIndex{343536373839404142434445464748495051525354 printf("(%d,%d) ",answer[PrintIndex].line+1,answer[PrintIndex].row+1}/* 每10个答案一组,与其他组隔两行 */if((asnnum % 10) == 0)printf("\n\n");}/* 清空占用标志,寻找下一组解 */rowoccu[RowIndex] = notoccued;LeftTop_RightDown[LineIndex-RowIndex+N-1] = notoccued;RightTop_LefttDown[LineIndex+RowIndex] = notoccued;}}}main(){inti = 0;/* 调用求解函数*/nextline(i);/* 保持屏幕结果*/getchar();}C语言实现图形实现对于八皇后问题的实现,如果结合动态的图形演示,则可以使算法的描述更形象、更生动,使教学能产生良好的效果。
八皇后源代码及流程图
目录一需求分析 (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 <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++课程设计八皇后问题
安徽建筑工业学院数据结构设计报告书院系数理系专业信息与计算科学班级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,关键的类好了,然后编辑好类的成员,然后编辑主函数利用好这些类的成员,让其运算出结果。
八皇后以及N皇后问题分析
⼋皇后以及N皇后问题分析⼋皇后是⼀个经典问题,在8*8的棋盘上放置8个皇后,每⼀⾏不能互相攻击。
因此拓展出 N皇后问题。
下⾯慢慢了解解决这些问题的⽅法:回溯法:回溯算法也叫试探法,它是⼀种系统地搜索问题的解的⽅法。
回溯算法的基本思想是:从⼀条路往前⾛,能进则进,不能进则退回来,换⼀条路再试。
在现实中,有很多问题往往需要我们把其所有可能穷举出来,然后从中找出满⾜某种要求的可能或最优的情况,从⽽得到整个问题的解。
回溯算法就是解决这种问题的“通⽤算法”,有“万能算法”之称。
N皇后问题在N增⼤时就是这样⼀个解空间很⼤的问题,所以⽐较适合⽤这种⽅法求解。
这也是N皇后问题的传统解法,很经典。
算法描述:1. 算法开始,清空棋盘。
当前⾏设为第⼀⾏,当前列设为第⼀列。
2. 在当前⾏,当前列的判断放置皇后是否安全,若不安全,则跳到第四步。
3. 在当前位置上满⾜条件的情况: 在当前位置放⼀个皇后,若当前⾏是最后⼀⾏,记录⼀个解; 若当前⾏不是最后⼀⾏,当前⾏设为下⼀⾏,当前列设为当前⾏的第⼀个待测位置; 若当前⾏是最后⼀⾏,当前列不是最后⼀列,当前列设为下⼀列; 若当前⾏是最后⼀⾏,当前列是最后⼀列,回溯,即清空当前⾏以及以下各⾏的棋盘,然后当前⾏设为上⼀⾏,当前列设为当前⾏的下⼀个待测位置; 以上返回第⼆步。
4.在当前位置上不满⾜条件: 若当前列不是最后⼀列,当前列设为下⼀列,返回到第⼆步; 若当前列是最后⼀列,回溯,即,若当前⾏已经是第⼀⾏了,算法退出,否则,清空当前⾏以及以下各⾏的棋盘,然后,当前⾏设为上⼀⾏,当前列设为当前⾏的下⼀个待测位置,返回第⼆步。
如何判断是否安全:把棋盘存储为⼀个N维数组a[N],数组中第i个元素的值代表第i⾏的皇后位置,这样便可以把问题的空间规模压缩为⼀维O(N),在判断是否冲突时也很简单, ⾸先每⾏只有⼀个皇后,且在数组中只占据⼀个元素的位置,⾏冲突就不存在了, 其次是列冲突,判断⼀下是否有a[i]与当前要放置皇后的列j相等即可。
用CSP(约束满足问题)方法解决八皇后问题
conflictNum++; } } //检查同一列是否有冲突 j=column; for(i=0;i<N;i++) { if((i!=row)&&(queenBoard[i][j]==QUEEN)) {
//如果同一列其它位置有皇后,记录冲突点数 conflictNum++; } } //检查'\'斜线是否有冲突 if(row>column) { i=row-column; j=0; } else { i=0; j=column-row; } for(;(i<N)&&(j<N);i++,j++ ) { if((i!=row)&&(queenBoard[i][j]==QUEEN)) { //如果'\'斜线其它位置有皇后,记录冲突点数 conflictNum++; } } //检查'/'斜线是否有冲突 if((row+column)<N) { i=row+column; j=0; } else { i=N-1; j=row+column-N+1; } for(;(i>=0)&&(j<=N);i --,j++)
该列的每一行中与该位置有冲突的皇后数,选取冲突数最小的位置作为新的该列的皇后位置, 并记录下该列被放置皇后的信息,记录被放置皇后信息的目的是为了避免算法陷入死循环。
为了更清楚地说明该算法,假设算法某一步搜索到的状态如下:
此时按照最小冲突算法,第二列、第六列、第七列和第八列的皇后 有冲突,则当计算第六列 的每一行的与该位置有冲突的皇后数时,结果如下:
八皇后问题的解决完整
八皇后问题的解决完整 Standardization of sany group #QS8QHH-HHGX8Q8-GNHHJ8-HHMHGN#淮阴工学院数据结构课程设计报告设计题目:八皇后2008 年 6 月 25 日设计任务书摘要:八皇后问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子.因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。
而本课程设计本人的目的也是通过用c++语言平台将一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现.使用递归方法最终将其问题变得一目了然,更加易懂。
关键词:八皇后 ; c++ ; 递归法目录.1. 课题综述1. 1课题的来源及意义八皇后问题是一个古老而着名的问题,该问题是十九世纪着名的数学家高斯1850年提出的。
在国际象棋中,皇后是最有权利的一个棋子;只要别的棋子在它的同一行或同一列或同一斜线(正斜线或反斜线)上时,它就能把对方棋子吃掉。
所以高斯提出了一个问题:在8*8的格的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后都不能处于同一列、同一行、或同一条斜线上面,问共有多少种解法。
到了现代,随着计算机技术的飞速发展,这一古老而有趣的数学游戏问题也自然而然的被搬到了计算机上。
运用所学计算机知识来试着解决这个问题是个锻炼和提高我自己编程能力和独立解决问题能力的好机会,可以使我增强信心,为我以后的编程开个好头,故我选择了这个有趣的课题。
1. 2 面对的问题1)解决冲突问题:这个问题包括了行,列,两条对角线;列:规定每一列放一个皇后,不会造成列上的冲突;行:当第I行被某个皇后占领后,则同一行上的所有空格都不能再放皇后,要把以I为下标的标记置为被占领状态;2)使用数据结构的知识,用递归法解决问题。
八皇后问题 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语⾔回溯法解⼋皇后问题(⼋皇后算法)⼋皇后问题(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.#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语言版)
#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 种状态为: */@ * * * * *@* * * *。
八皇后问题爬山法实现(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 解决办法
return true; }
void displayqueen(vector<int> x, int N, int kind) {
if(kind == 1) {
cout<<"第"<<sum<<"个解:";
for(int i=1; i<N+1; i++) {
x[t] = i;
if(place(t, x)) {
backtrack(t+1, x, N, kind); } } } }
bool place(int k, vector<int> x) {
for(int j=1; j<k; j++) {
if((abs(k-j) == abs(x[k]-x[j])) || (x[k] == x[j])) {
for(i=1; i<N+1; i++) {
for(int j=1; j<N+1; j++) {
S[i][x[i]] = 1; } }
cout<<"第"<<sum<<"个解:"<<endl;
for(i=1; i<N+1;ห้องสมุดไป่ตู้i++) {
for(int j=1; j<N+1; j++) {
cout<<S[i][j]<<' '; } cout<<endl; } } }
八皇后问题的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.⼗⾏内的⼋皇后...对知乎上各路⼤⼤的炫技佩服的五体投地,更改了⼀下上⼀代码,勉强也达到了⼗⾏的要求。
1213:八皇后问题
1213:⼋皇后问题⾸先可以试图去简化问题,将问题转化为为每⼀列确定⼀个有效的⾏号。
因为同⼀列只能有⼀个皇后,并且需要在⼋列中确定⼋个皇后,即每⼀列都必定有且只有⼀个皇后。
经过简化后,显然,通过⼀个⼀维数组即可以确定⼀组有效解。
关于check:不为同⼀⾏或同⼀列的判定⽐较简单(这⾥省略)(i1,j1)与(i2,j2)在同⼀条斜线上的判定:i1-i2==j1-j2 || i1-i2==j2-j1问题经过这样⼀次抽丝剥茧后,剩余的思路⼤致就是深度搜索、临界输出。
特别重复:a[j]表⽰第j列的皇后所在的⾏数1 #include<iostream>2 #include<cstdio>3using namespace std;45const int N=10;6int ans,a[N];7void print(){8 printf("No. %d\n",++ans);9for(int i=1;i<=8;i++){10for(int j=1;j<=8;j++)11if(a[j]==i)printf("1 ");12else printf("0 ");13 printf("\n");14 }15 }16bool check(int x,int d){17for(int i=1;i<d;i++){18if(a[i]==x||x-a[i]==d-i||x-a[i]==i-d)19return0;20 }21return1;22 }23void solve(int d){24if(d==9){25 print();26return;27 }28for(int i=1;i<=8;i++){29if(check(i,d)){30 a[d]=i;31 solve(d+1);32 }33 }34 }35int main(){36 solve(1);37return0;38 }。
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函数中,我们检查当前位置是否合法,即与前面的皇后不冲突。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
c[i+iColumn]=1; //标记,下一次该从对角线上不能放皇后
if(i<7)
qu(i+1); //如果行还没有遍历完,进入下一行
else //否则输出
{
//输出棋盘状态
int iLine,iColumn;
printf("第%d种状态为:\n",++iQueenNum);
*其中定义了通过控制台进行数据输入和数据输出的函数,
*主要是一些用户通过按键盘产生的对应操作,比如getch()函数等等。
*/
static char Queen[8][8];
static int a[8];
static int b[15];
static int c[15];
static int iQueenNum=0; //记录总的棋盘状态数
* * * * @ * * *
* * @ * * * * *
第4种状态为:
@ * * * * * * *
* * * * * * @ *
* * * * @ * * *
* * * * * * * @
* @ * * * * * *
* * * @ * * * *
* * * * * @ * *
* * @ * * * * *
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)
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; //标记,下一次该列上不能放皇后
第10种状态为:
* @ * * * * * *
* * * * * * @ *
* * @ * * * * *
* * * * * @ * *
* * * * * * * @
* * * * @ * * *
@ * * * * * * *
* * * @ * * * *
*/
* * * * * * @ *
* * * @ * * * *
* @ * * * * * *
* * * * @ * * *
第3种状态为:
@ * * * * * * *
* * * * * * @ *
* * * @ * * * *
* * * * * @ * *
* * * * * * * @
* @ * * * * * *
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++)
{
getch();
}
}
//如果前次的皇后放置导致后面的放置无论如何都不能满足要
//求,则回溯,重置
Queen[i][iColumn]='*';
a[iColumn]=0;
b[i-iColumn+7]=0;
c[i+iColumn]=0;
}
}
}
/*
输出效果:
第1种状态为:
@ * * * * * * *
* * * * @ * * *
#include <stdio.h>
#include "windows.h"
#include<conio.h>
#include <stdlib.h>
#include <windows.h>
//添加下边这一行
#include<conio.h>
/* conio是Console Input/Output(控制台输入输出)的简写,
@ * * * * * * *
* * * * * * * @
* * * * * @ * *
* * @ * * * * *
第8种状态为:
* @ * * * * * *
* * * * * @ * *
@ * * * * * * *
* * * * * * @ *
* * * @ * * * *
* * * * * * * @
第5种状态为:
* @ * * * * * *
* * * @ * * * *
* * * * * @ * *
* * * * * * * @
* * @ * * * * *
@ ** * @ * * *
第6种状态为:
* @ * * * * * *
* * * * @ * * *
* * * * * * @ *
@ * * * * * * *
* * @ * * * * *
* * * * * * * @
* * * * * @ * *
* * * @ * * * *
第7种状态为:
* @ * * * * * *
* * * * @ * * *
* * * * * * @ *
* * * @ * * * *
* * * * * * * @
* * * * * @ * *
* * @ * * * * *
* * * * * * @ *
* @ * * * * * *
* * * @ * * * *
第2种状态为:
@ * * * * * * *
* * * * * @ * *
* * * * * * * @
* * @ * * * * *
* * @ * * * * *
* * * * @ * * *
第9种状态为:
* @ * * * * * *
* * * * * @ * *
* * * * * * * @
* * @ * * * * *
@ * * * * * * *
* * * @ * * * *
* * * * * * @ *
* * * * @ * * *
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;