八皇后问题,递归法实现

  八皇后问题,是19世纪著名的数学家高斯在1850年提出的:在8×8格的国际象棋盘上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列、同一斜线上,试问有多少种摆法?高斯先生给出的答案是“76”种,实际是76种吗?

  八皇后问题是回溯算法的典型应用,但是本文提供递归的求法。

  递归的核心思想可以总结成:把一个复杂的问题无限缩小,每个小问题的解法都是一样的,最终归结于求解每个小问题的原型。递归编程的思路可以假设所有的问题都已解决,来到结束条件,这是非常简单的,然后再调用自身求解整个问题。虽然递归的效率比较低,但是可以大大降低思考的程度。

  八皇后问题的递归思路为:先放置第一个皇后;把第一个皇后所能攻击到的区域排除,放置第二个皇后;把第二个皇后所能攻击到的区域排除,放置第三个皇后......直至放置第八个皇后,第八个皇后所能放置的区域只有一个格子。

  1 //八皇后问题,递归法实现
  2 #include <stdio.h>
  3
  4 int count = 0;
  5
  6 //判断第row行j列是否安全,判断列、左上、右上、左下、右下
  7 int Safe( int row, int j, int (*chess)[8])
  8 {
  9     int i, k, flag1=0, flag2=0, flag3=0, flag4=0, flag5=0;
 10
 11     //判断列方向是否安全
 12     for( i=0; i<8; i++)
 13     {
 14         if(*(*(chess+i)+j) !=0)
 15         {
 16             flag1 = 1; //不安全
 17             break;
 18         }
 19     }
 20
 21     //判断左上方是否安全
 22     for( i=row, k=j; i>=0 && k>=0; i--,k--)
 23     {
 24         if(*(*(chess+i)+k) !=0)
 25         {
 26             flag2 = 1; //不安全
 27             break;
 28         }
 29     }
 30
 31     //判断右下方是否安全
 32     for( i=row, k=j; i<8 && k<8; i++,k++)
 33     {
 34         if(*(*(chess+i)+k) !=0)
 35         {
 36             flag3 = 1; //不安全
 37             break;
 38         }
 39     }
 40
 41     //判断右上方是否安全
 42     for( i=row, k=j; i>=0 && k<8; i--,k++)
 43     {
 44         if(*(*(chess+i)+k) !=0)
 45         {
 46             flag4 = 1; //不安全
 47             break;
 48         }
 49     }
 50
 51     //判断左下方是否安全
 52     for( i=row, k=j; i<8 && k>=0; i++,k--)
 53     {
 54         if(*(*(chess+i)+k) !=0)
 55         {
 56             flag5 = 1; //不安全
 57             break;
 58         }
 59     }
 60
 61     if( flag1 || flag2 || flag3 || flag4 || flag5)
 62         return 0;
 63     else
 64         return 1;
 65 }
 66
 67 // row :起始行
 68 //  n  :列数
 69 // (*chess)[8] :指向棋盘每一行的指针
 70 void EightQueen( int row, int n, int (*chess)[8])
 71 {
 72     int i, j, chessTemp[8][8];    //用于存放当前形式的棋盘
 73
 74     for( i=0; i<8; i++)
 75     {
 76         for( j=0; j<8; j++)
 77         {
 78             chessTemp[i][j] = chess[i][j];
 79         }
 80     }
 81
 82     if( 8==row )    //递归终止条件,即假设已经找到一种棋盘分布,将它打印
 83     {
 84         printf("第 %d 种棋盘:\n",count+1);
 85         for( i=0; i<8; i++)
 86         {
 87             for( j=0; j<8; j++)
 88             {
 89                 printf("%d ",*(*(chessTemp+i)+j));
 90             }
 91             printf("\n");
 92         }
 93         printf("\n");
 94         count++;
 95     }
 96     else    //进入递归
 97     {
 98         for( j=0; j<n; j++) //对第row行的各列扫描
 99         {
100             if( Safe( row, j, chess))   //如果第row行,j列安全
101             {
102                 for( i=0; i<8; i++)
103                 {
104                     *(*(chessTemp+row)+i) = 0;  //第row行赋0
105                 }
106                 *(*(chessTemp+row)+j) = 1;      //第row行,j列赋1
107
108                 EightQueen( row+1, n, chessTemp);
109             }
110         }
111     }
112 }
113
114 int main()
115 {
116     int chess[8][8], i, j;
117
118     for( i=0; i<8; i++)
119     {
120         for( j=0; j<8; j++)
121         {
122             chess[i][j] = 0;
123         }
124     }
125
126     EightQueen(0, 8, chess); //第0行开始,共有8列
127     printf("共有 %d 种方法:",count);
128
129     return 0;
130 }
时间: 2024-10-15 09:48:47

八皇后问题,递归法实现的相关文章

八皇后问题——递归+回溯法

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 高斯认为有76种方案.1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果. 求解过程: 采用遍历的办法,就是采用将每种情况都验证的办法最终找出问题的解,但是蛮力遍历的话,需要遍历的数据量太大,计算时间花费太大,所以在遍历

八皇后问题 递归实现 C语言 超详细 思路 基础

八皇后问题 :假设 將八个皇后放到国际象棋盘上,使其两两之间无法相互攻击.共有几种摆法? 基础知识: 国际象棋里,棋盘为8X8格. 皇后每步可以沿直线.斜线 走任意格. 思路: 1.想把8个皇后放进去,肯定最终每行只有一个皇后,每列只有一个皇后. 2.设个二维数组chess [ i ] [ j ] 模拟棋盘,cas存放摆法.i j 是表示i行j列: 写一个用于递归的函数,思路如下 3.从上往下一行行的放皇后,放下一行时从最左边(第0列)放起,如果不能放就往右挪一格再试.注意判断右边有没有越界出棋

八皇后问题-回溯法解

八皇后问题:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. int g_number = 0;? //多少种摆放方法?void EightQueen(){? ?const int queens = 8;? //棋盘大小?? ?int ColumnIndex[queens];? //列索引?//遍历行? ?for(int i = 0; i < queens; ++ i)?? ? ? ?ColumnIndex[i] = i;

八皇后问题——回溯法(python&amp;&amp;JAVA)

八皇后问题,是一个古老而著名的问题,问题如下: 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 上边是一个8*8的国际棋盘,可以看到棋盘中的每个格子都标有数字.每个数字都是两位,十位数字表示该格子所在的行,而个位数字表示该格子所在的列. 这样不难发现,处在同一行的两个格子其十位数都相同,处在同一列的两个格子其个位数都相同,处在同一斜线的两个格子有:|两个数字个位数的差|=|两个数字十位数的差|. 主要的三个限制条件明白了

java实现八皇后问题(递归和循环两种方式)

循环方式: package EightQueens; public class EightQueensNotRecursive { private static final boolean AVAILABLE = true; private int squares = 8, norm = squares - 1; private int positionInRow[] = new int[squares]; private int p=-1; private boolean[] rows = n

八皇后问题-回溯法(matlab)

1.问题描述 八皇后问题是十九世纪著名数学家高斯于1850年提出的.问题是:在8*8的棋盘上摆放8个皇后,使其不能互相攻击,即任意的两个皇后不能处在同意行,同一列,或同意斜线上. 2.matlab代码 function PlaceQueen(row,stack,N)%回溯法放置皇后 if row>N PrintQueen(N,stack);%打印棋盘 else for col=1:N stack(row)=col; if row==1||Conflict(row,col,N,stack)%检测是

八皇后之回溯法解决[转]

问题描述: 要在8*8的国际象棋棋盘中放8个皇后,使任意两个皇后都不能互相吃掉.规则是皇后能吃掉同一行.同一列.同一对角线的棋子.如下图即是两种方案: . 解决方案: 8*8的棋盘要摆放8个皇后,且不能同行同列同对角线,那么每行必定会有一个皇后.我们可以设一个数组a用来存放每一行皇后的位置,元素值表示第几列(如a[1]=5表示第一行的皇后处于第五个格).然后只需要求出数组a的值 问题就解决了,下面介绍三种回溯解法: 1.八个for循环.用枚举的办法,八个for循环分别枚举每一行的8个位置,但是我

八皇后问题递归代码

听了下别人的讲解后,最后仔细理解了下所谓的八皇后问题. 怎么说呢,感觉有点像搜索的做法. #include<stdio.h> int count=0; //row行,j列: int notDanger(int row,int j,int (*chess)[8]){ int i,k,flag1=0,flag2=0,flag3=0,flag4=0,flag5=0; //注意这里row与j不能直接使用: //判断列的方向有无危险: for(i=0;i<8;i++){ if(*(*(chess+

八皇后回溯递归 40行不到

个人感觉代码还算精简,比较容易混淆的一点是,board[] 数组,数组下表指的是八皇后棋盘的行,数组下标对应的值指的是八皇后棋盘的列,至于abs()可以去百度,是一个求绝对值的函数 #include <iostream> using namespace std ; #define N 8 static int sum = 0 ; const int max = N ; void print (int board []) { for(int i = 0 ;i < max ;i++) { c

2、八皇后问题——回溯法

/** * */ package unit1; /** * @author * @version 创建时间:2015-10-30 下午02:55:24 类说明 */ public class EightQueensNotRecursive { private static final boolean AVAILABLE = true; private int squares = 16, norm = squares - 1; private int positionInRow[] = new i