回溯法 八皇后
回溯法课程知识点总结

回溯法课程知识点总结在回溯法中,通常使用递归的方式来遍历解空间树,每次遍历到下一层时,都会尝试选择一个决策。
如果选择的决策不满足约束条件,则进行回溯,取消该决策,重新选择其他决策。
当所有的决策都尝试完毕后,就回到上一层继续尝试其他决策,直至搜索到满足约束条件的解,或者搜索完整个解空间树。
回溯法的优点是能够有效地遍历解空间树,找到满足约束条件的解。
它也具有灵活性高、适用范围广等优点。
但同时,回溯法也存在着时间复杂度高、搜索空间大等缺点。
在实际应用中,回溯法通常需要结合具体问题进行适当地优化,以提高搜索效率。
下面我们将介绍回溯法的具体实现和应用。
1. 回溯法的实现回溯法的实现通常由两部分组成:递归函数和决策函数。
递归函数用于遍历解空间树,决策函数用于判断是否满足约束条件和进行决策选择。
下面以求解八皇后问题为例,介绍回溯法的实现。
八皇后问题是一个经典的回溯法应用题目,在一个8×8的棋盘上摆放八个皇后,使得它们互相不攻击。
互相不攻击的条件是:任意两个皇后不在同一行、同一列或同一斜线上。
```pythondef solve_n_queens(n):res = []def backtrack(path):if len(path) == n:res.append(path[:])returnfor i in range(n):if is_valid(path, i):path.append(i)backtrack(path)path.pop()def is_valid(path, col):row = len(path)for i in range(row):if path[i] == col or abs(row - i) == abs(col - path[i]):return Falsereturn Truebacktrack([])return res```在上面的代码中,solve_n_queens函数用于求解八皇后问题,其实现思路如下:首先,定义一个回溯函数backtrack,用于遍历解空间树。
八皇后问题(经典算法-回溯法)

⼋皇后问题(经典算法-回溯法)问题描述:⼋皇后问题(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;}。
八皇后问题详细的解法

若无法放下皇后则回到上一行, 即回溯
当n行的皇后都已确定后,我们 就找到了一种方案
check2 (int a[ ],int n)
queen21(例) 1 b加约束的枚举算法{//i多nt次i; 被调用,只是一重循环
{int a[9]; for (a[1]=1;a[1]<=8;a[1]++) for (a[2]=1;a[2]<=8;a[2]++)
八皇后问题
1
1八皇后问题背景 2盲目的枚举算法 3加约束的枚举算法 4回溯法及基本思想 5 回溯法应用 6八皇后问题的递归回溯算法 7八皇后问题的非递归回溯算法
2
【背景】 八皇后问题是一个以国际象棋为背
景的问题: 如何能够在 8×8 的国际象棋棋盘上
放置八个皇后,使得任何一个皇后都 无法直接吃掉其他的皇后?为了达到 此目的,任两个皇后都不能处于同一 条横行、纵行或斜线上。
for(a[8]=1;a[8]<=8;a[8]++) 此算法可读性很好,
{if (check(a,8)==0)continue; 体现了“回溯”。但
else for(i=1;i<=8;i+nt(a[i]); }
题,而不能解决任意
}}}}}}}
的n皇后问题。
18
2 回溯法应用-算法说明
按什么顺序去搜? 目标是没有漏网之鱼,尽量速度快。
5
2 【问题设计】盲目的枚举算法
a 盲目的枚举算法
通过8重循环模拟搜索空间中的88个状态;
按枚举思想,以DFS的方式,从第1个皇后在第1列开 始搜索,枚举出所有的“解状态”:
从中找出满足约束条件的“答案状态”。
八皇后问题

八皇后问题编辑八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。
该问题是国际西洋棋棋手马克斯·贝瑟尔于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语言实现图形实现对于八皇后问题的实现,如果结合动态的图形演示,则可以使算法的描述更形象、更生动,使教学能产生良好的效果。
回溯法解八皇后问题

fprintf(fp," ");
}
printf("%d\n", i);
fprintf(fp, "%d\n", i);
}
printf
(".......................................................\n");
fprintf(fp,
/*/
#include <stdio.h>
#include <math.h>
#define false 0
#define true 1
#define quesize 8
int gx[quesize+1];
int sum=0;
int place( int k );
void print( int a[] );
fprintf(fp,"the sum of the ways of queens:%d\n", sum);
printf("the sum of the ways of queens:%d\n", sum);
fclose(fp);
return 1;
}
/*/////////////////////////////////////////////////////////////////////
{
int i = 1;
while ( i < k )
{ if ( ( gx[i] == gx[k] ) || ( abs( gx[i] - gx[k] )==abs( i - k ) )
算法入门经典-第七章例题7-2八皇后问题

算法⼊门经典-第七章例题7-2⼋皇后问题原本利⽤回溯思想解决的经典⼋皇后问题,其实也是可以⽤递归解决的~⼋皇后的递归解决思路:从第⼀⾏开始,依次判断0~8列的哪⼀列可以放置Queen,这样就确定了该⾏的Queen的位置,然后⾏数递增,继⽽递归实现下⼀⾏的判断,依次类推直到⾏数增加到8(⾏数从0开始的),此时为递归-----归的条件,即表⽰⼀种⼋皇后的解决⽅法完成,打印结果;之后进⾏下⼀种解决⽅法的寻找,⼤致思路个⼈理解是这样noDanger(row,j,(*chess)[8])函数是判断第row⾏第j列是否可以放置Queen#include<stdio.h>int count=0;//参数row:起始⾏//参数n:表⽰列数//参数(*chess)[8]表⽰指向棋盘每⼀⾏的指针int NotDanger(int row,int j,int (*chess)[8])//⽐较不同⾏同列上是否有其他皇后{int i,k,flag1=0,flag2=0,flag3=0,flag4=0,flag5=0;//判断列⽅向for(i=0;i<8;i++){if(*(*(chess+i)+j)!=0) //在这之前列上有其他皇后{flag1=1;break;}}for(i=row,k=j;i>=0&&k>=0;i--,k--){if(*(*(chess+i)+k)!=0) //左上⽅{flag2=1;break;}}for(i=row,k=j;i<8&&k<8;i++,k++){if(*(*(chess+i)+k)!=0) //右下⽅{flag3=1;break;}}for(i=row,k=j;i>=0&&k<8;i--,k++){if(*(*(chess+i)+k)!=0) //右上⽅{flag4=1;break;}}for(i=row,k=j;i<8&&k>=0;i++,k--){if(*(*(chess+i)+k)!=0) //左下⽅{flag5=1;break;}}if(flag1||flag2||flag3||flag4||flag5){return0;//如果有⼀个位置被占有危险}else return1;} /*int noDanger(int row,int j,int (*chess)[8]){int flag1=0,flag2=0,flag3=0,flag4=0,flag5=0;int i,k;//判断列for(i=0;i<8;i++){if(*(*(chess+i)+j)!=0){flag1=1;break;}}//判断左上⽅for(i=row,k=j;i>=0&&k>=0;i--,k--){if(*(*(chess+i)+k)!=0){flag2=1;break;}}//判断右下⽅for(i=row,k=j;i<8&&k<8;i++,k++){if(*(*(chess+i)+k)!=0){flag3=1;break;}}//判断左下⽅for(i=row,k=j;i<8&&k>=0;k--,i++){if(*(*(chess+i)+k)!=0){flag4=1;break;}}//判断右上⽅for(i=row,k=j;i>=0&&k<8;k++,i--){if(*(*(chess+i)+k)!=0){flag5=1;break;}}if(flag1||flag2||flag3||flag4||flag5){return 0;}else{return 1;}} */EightQueen(int row,int n,int (*chess)[8]){int chess2[8][8];int i,j;for(i=0;i<8;i++){for(j=0;j<8;j++){chess2[i][j]=chess[i][j];}}if(8==row){printf("第%d 种\n",count+1);for(i=0;i<8;i++){for(j=0;j<8;j++)printf("%3d ",*(*(chess2+i)+j));printf("\n");}count++;}else{//判断这个位置是否危险 j<列for(j=0;j<n;j++){if(NotDanger(row,j,chess2))//尝试每⼀列是否危险 {for(i=0;i<8;i++){//整⾏所有列的位置赋值为0*(*(chess2+row)+i)= 0;}*(*(chess2+row)+j)=1;//皇后的位置赋值为1EightQueen(row+1,n,chess2);//继续往下⼀⾏递归 }}}}int main(){int chess[8][8],i,j;for(i=0;i<8;i++){for(j=0;j<8;j++)chess[i][j]=0;}EightQueen(0,8,chess);printf("总共有%d种解决⽅法",count);return0;}。
八皇后问题的解决方案

算法总结
3
解决八皇后问题常用算法
3.1
枚举法解决八皇后问题
3.2
非递归回溯法解决八皇后问题
3.3
递归回溯法解决八皇后问题
3.0
八皇后问题约束条件
a( i ) 1 2 3 4 5 6 7 8 a( 1) 2 0 -1 3 -2 4 -3 5 -4 6 -5 7 -6 8 -7 9
a( 2 ) a( 3 ) a( 4) a( 5 ) a( 6) a( 7 ) a( 8)
9 3 10 2 11 1 12 0 13 -1 14 -2
9 5 10 4 11 3 12 2 13 1 14 0 15 -1
9 7 10 6 11 5 12 4 13 3 14 2 15 1 16 0
3.0
八皇后问题约束条件
a( i ) =j 第i行j列放置皇后
判断不同列 a(i)≠a(j) 判断不同对角线 i-a(i)≠j-a(j) 判断不同反对角线 i+a(i)≠j+a(j)
取下一个………………
取下一个q (1)
用语言编程
For q1 = 1 To 8 For q2 = 1 To 8 For q3 = 1 To 8 For q4 = 1 To 8 For q5 = 1 To 8 For q6 = 1 To 8 For q7 = 1 To 8 For q8 = 1 To 8 q(q1) = q1 : q(q2) = q2 : q(q3) = q3 : q(q4) = q4 q(q5) = q5 : q(q6) = q6 : q(q7) = q7 : q(q8) = q8 If putdown(q)=1 Then printstr(q) Next q8 Next q7 Next q6 Next q5 Next q4 Next q3 Next q2 Next q1
八皇后问题的动态求解

3 动 态 求解 8皇 后 问 题
通 常 编程 求 解 N后 问题 ,只 能看 到求 解 的 结 果 ,观 察 不 到 求 解 过 程 中 的 试 探 和 回溯 的 过 程 。 以 8皇 后 问 题 为 例 ,用 C #
中 ,按 照深 度 优 先 的 策 略 ,从 根 结 点 出 发搜 索 解 空 间树 。算 法 搜 索 到解 空 间树 的任 一 结 点 时 ,总 是先 判 断该 结 点是 否肯 定 不 包 含 问题 的解 。如 果 肯 定 不 包 含 ,则跳 过对 以该 结 点 为根 的子 树 的系 统 搜 索 ,逐 层 向 其 祖 先 结 点 回溯 。 否 则 ,进 入 该 子 树 , 继 续 按 深 度 优先 的策 略 进 行 搜 索 。用 该 方 法 可 以 系 统 地搜 索 一 个 问 题 的所 有解 或任 一 解 , “ 回溯 法 ” 也 是 递 归 过 程 的 一 种 重
)
}
i(u g () / 口 第 n个 皇 后位 置 合 法 , 归 放 置 fJ d en) / 果 女 递 } n 1 皇 后 涕 + 个
{ L y e n n 4 1: aLeabharlann Qu e ( ) - )
)
开始 求 解 ” 钮 的单 击 事 件 按
p ia e v i t L y r t od b n a v
f
, 入 本 函 数 前 , N× 格 棋盘 的 前 1 已 经 放 置 了 i / 进 在 N 一 列 —
叭 个皇后o
iiN 则输 出 得 到 的 一个 解 决 方 案 ; f> ) (
es le
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
回溯法(8皇后问题)
1.1算法原理
回溯算法实际是一个类似枚举的搜索尝试方法,其基本思想是在搜索尝试中找问题的解,采用了一种“走不通就掉头”的思想,作为其控制结构。
从一条路往前走,能进则进,不能进则退回来,换一条路再试。
八皇后问题就是回溯算法的典型,第一步按照顺序放一个皇后,然后第二步符合要求放第2个皇后,如果没有符合条件的位置符合要求,那么就要改变第一个皇后的位置,重新放第2个皇后的位置,直到找到符合条件的位置就可以了。
回溯在迷宫搜索中使用很常见,就是这条路走不通,然后返回前一个路口,继续下一条路。
回溯算法说白了就是穷举法。
不过回溯算法使用剪枝函数,剪去一些不可能到达最终状态(即答案状态)的节点,从而减少状态空间树节点的生成。
回溯法是一个既带有系统性又带有跳跃性的的搜索算法。
它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。
算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。
如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。
否则,进入该子树,继续按深度优先的策略进行搜索。
回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。
而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。
用回溯法搜索解空间树时,通常采用两种策略来避免无效搜索,提高回溯法的搜索效率。
其一是用约束函数在扩展结点处剪去不满足约束的子树;其二是用限界函数剪去不能得到最优
解的子树。
1.2算法适用性
它适用于解一些组合数较大的问题,有条件限制的枚举,即优化的枚举.
1.3算法描述
8皇后回溯算法
1.设Column[8]数组依次存储第一行到第八行的列位置,QUEEN_NUM=8,皇后个数
2.从第一行第一列开始放置,开始放置下一行的皇后(当且仅当前行的皇后位置正确时)
3.判断放置位置是否合理:Column[i]==Column[n],判断是否在同一列,
abs(Column[i]-Column[n])==(n-i)),判断时候在斜线上。
如果不在用一列,同一斜线上,则位置合理,进行下一行皇后放置,否则回溯
4.当最后一行皇后放置正确时,一种放置方法结束,进行下一种方法,查找。
1.4程序实现及程序截图
1.41源代码:
#include<stdio.h> //包含一般操作的库函数
#include<math.h> //包含数学公式的库函数
constint QUEEN_NUM=8; //皇后个数
int Column[8]; // 存储皇后的列数
static intCol_N[8]={0} ; //存储首行每一列的解的个数
void queen(int n); //放置皇后位置
int output(); //输出结果
int judge(int n); //判断操作是否合理
intnum=0; //方案个数
int o=0; //标记全部方案是否寻找完毕,因为只要方案存在,则输出函数一直运行main()
{
queen(0);
if (o) //全部方案寻找完毕
{
inti;
i=0;
printf("全部可行方案已寻找完毕,一共%d种方案\n\n",num);
for(i=0;i<QUEEN_NUM;i++) //统计解决方案
printf("第1行皇后位于第%d列解决方案个数:%d\n",i+1,Col_N[i]);
}
getchar(); // 程序暂停,便于查看,防闪退
}
void queen(int n) //放入第n+1行皇后位置
{
inti; //当前行的第i列
if(n==QUEEN_NUM) //第n行是否为最后一行
{
output(); //是则输出解决方案
}
for(i=1;i<=QUEEN_NUM;i++) // 不是最后一行
{
Column[n]=i; //将第n+1个皇后放入第i列
if(judge(n)) //判断当前操作是否合理,不合理则探索第i+1列,直到最后一列(回溯过程)
queen(n+1); // 合理则进行下一行放置皇后操作
}
}
int judge(int n) // 判断第n+1行皇后位置是否合理
{
inti; //列
for(i=0;i<n;i++) //例数判断是否与前n行有冲突
{
if(Column[i]==Column[n]) //列数相同
return 0;
if(abs(Column[i]-Column[n])==(n-i))// 在同一对角线上
return 0;
}
return 1; //遍历完毕,没有冲突
}
int output() //打印出合理方案
{
intj,k,CN;
o=1;
printf("********方案:%d********\n",++num);//每打印一次,方案总数+1
for(j=0;j<QUEEN_NUM;j++) //行循环列循环
{
for(k=1;k<=QUEEN_NUM;k++) // 打印方案
{
if(Column[j]==k) // 标记k列皇后的位置
{
if(j==0) //存储第一行i列解决方案
{
CN=k-1;//取出解决方案个数
Col_N[k-1]++;
}
printf("■");
}
else // 标记非皇后位置
printf("□");
}
printf("\n"); // 换行输出,形成矩阵
}
printf("\n"); //当前可行方案打印结束,换行
printf("第1行皇后位于第%d列:\n累计解决方案的个数:* %d *\n" ,CN+1,Col_N[CN]);
getchar(); //( 控制自动输出,还是手动输出)
return (o);
}
1.42程序截图。