八皇后问题是一道经典的回溯问题。问题描述如下:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8*8个方格),使它们谁也不能被吃掉?

        看到这个问题,最容易想到的就是遍历穷举法,不过仔细一想,思路虽然非常清晰,但是需要遍历次数太多,时间复杂度很高。那么,我们应该怎么办呢?下面给出算法思路:

        算法思想:首先尝试在第一行放置第一个皇后,然后在第二行放置第二个使之与前面的皇后不构成威胁,依此类推。如果发现不能放置下一个皇后,就回溯到上一步,试着将皇后放在其他的位置。最后,或者尝试完所有的可能或者找到解决方案。
        这种算法思想与中国的一句古话“不撞南墙不回头”类似:一路向前走,直到走到死胡同,然后往回走,回到上一个岔路口,重新选择一个方向,继续向前走,直到到达目的地。
        下面给出了该算法的具体实现,用C、MATLAB、PYTHON分别进行了实现,由于程序给出了比较详细的注释,因此就不对具体程序解释说明了。

C语言实现:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define N 8//棋盘大小
  6.  
  7. int matrix[N][N];//存储皇后的位置,其实也可以用一维数组表示
  8.  
  9. void PrintQueen();//打印棋盘
  10. void PlaceQueen(int row);//放置皇后
  11. int Conflict(int row,int col);//检查当前皇后是否与之前的冲突
  12.  
  13. int main()
  14. {
  15. PlaceQueen(0);
  16. return 0;
  17. }
  18.  
  19. void PrintQueen()
  20. {
  21. static int solutionNum=0;//看总共有多少种情况
  22. solutionNum+=1;
  23. int row,col;
  24. printf("第%d种方法:\n",solutionNum);
  25. for(row=0;row<N;row+=1)
  26. {
  27. for(col=0;col<N;col+=1)
  28. {
  29. if(matrix[row][col])
  30. {
  31. printf("* ");
  32. }
  33. else
  34. {
  35. printf("- ");
  36. }
  37. }
  38. printf("\n");
  39. }
  40. printf("\n");
  41. }
  42.  
  43. int Conflict(int row,int col)
  44. {
  45. for (int m = 0; m <row ; m++)
  46. {
  47. for (int n = 0; n <N; n++)
  48. {
  49. if (matrix[m][n] == 1) // 每一行只有一个皇后
  50. {
  51. if ( n == col || abs(row - m) == abs(col - n) ) // 检查是否与之前的皇后冲突
  52. return false;
  53. }
  54. }
  55. }
  56. return true;
  57. }
  58.  
  59. void PlaceQueen(int row)
  60. {
  61. if(row>=N)//已经放置了N个皇后
  62. {
  63. PrintQueen();
  64. }
  65. else
  66. {
  67. for(int col=0;col<N;col++)
  68. {
  69. matrix[row][col]=1;
  70. if(row==0||Conflict(row,col))
  71. PlaceQueen(row+1);//递归调用
  72. matrix[row][col]=0;
  73. }
  74.  
  75. }
  76.  
  77. }

MATLAB实现

脚本文件Queen.m

  1. clear all
  2. clc
  3.  
  4. global solutionNum;
  5. solutionNum=0;%全局变量记录方法数
  6. N=8;%皇后个数
  7. matrix=zeros(N);%存储皇后位置信息
  8.  
  9. PlaceQueen(1,matrix,N)%调用放置方法

函数文件PlaceQueen.m

  1. function PlaceQueen(row,matrix,N)%回溯法放置皇后
  2.  
  3. if row>N
  4. PrintQueen(N,matrix);%打印棋盘
  5. else
  6. for col=1:N
  7. matrix(row,col)=1;
  8. if row==1||Conflict(row,col,N,matrix)%检测是否冲突
  9. PlaceQueen(row+1,matrix,N);
  10. end
  11. matrix(row,col)=0;
  12. end
  13. end
  14.  
  15. %子函数:检测冲突
  16. function result=Conflict(row,col,N,matrix)%检测是否冲突
  17.  
  18. result=1;
  19. for i=1:row-1
  20. for j=1:N
  21. if matrix(i,j)==1
  22. if ((j==col)||(abs(row-i)==abs(col-j)))%是否产生冲突:在同一直线,斜线上
  23. result=0;
  24. break;
  25. end
  26. end
  27. end
  28. if result==0
  29. break;
  30. end
  31. end
  32.  
  33. %子函数:打印棋盘信息
  34. function PrintQueen(N,matrix)
  35.  
  36. global solutionNum; %定义全局变量,来累积方法数
  37. solutionNum=solutionNum+1;
  38.  
  39. disp(['第',num2str(solutionNum),'种方法:'])
  40.  
  41. disp(matrix)

PYTHON实现:

  1. def conflict(state,nextX):#冲突检测函数
  2. nextY=len(state)
  3. for i in range(nextY):
  4. if abs(state[i]-nextX) in (0,nextY-i):#检测是否在同一直线、斜线
  5. return True
  6. return False
  7.  
  8. def queens(num=8,state=()): #放置皇后,采用元组state来存储皇后的位置
  9. for pos in range(num):
  10. if not conflict(state,pos):
  11. if len(state)==num-1:
  12. yield (pos,)
  13. else:
  14. for result in queens(num,state+(pos,)):
  15. yield (pos,)+result
  16.  
  17. for solution in queens(8):
  18. print (solution)
  19.  
  20. print('总共的方法数为:',len(list(queens(8))))
运行结果分别如下:


1、C语言的运行结果:


2、MATLAB语言的运行结果:


3、PYTHON语言的运行结果:
 

扩展:

上面的程序中,改变N的值就可以解决N皇后的问题了,但还可以用分治法来解决N皇后的问题,具体参见文献《N皇后问题解的构造和等价性分析》。下面的Matlab程序给出了一个简单的算法过程:
4皇后的一种放置方式:
     0     0     1     0
     1     0     0     0
     0     0     0     1
     0     1     0     0
根据4皇后的放置方式可以推导出16皇后的一种放置方式:
     0     0     0     0     0     0     0     0     0     0     1     0     0     0     0     0
     0     0     0     0     0     0     0     0     1     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     0     0     1     0     0     0     0
     0     0     0     0     0     0     0     0     0     1     0     0     0     0     0     0
     0     0     1     0     0     0     0     0     0     0     0     0     0     0     0     0
     1     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
     0     0     0     1     0     0     0     0     0     0     0     0     0     0     0     0
     0     1     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     1     0
     0     0     0     0     0     0     0     0     0     0     0     0     1     0     0     0
     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     1
     0     0     0     0     0     0     0     0     0     0     0     0     0     1     0     0
     0     0     0     0     0     0     1     0     0     0     0     0     0     0     0     0
     0     0     0     0     1     0     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     1     0     0     0     0     0     0     0     0
     0     0     0     0     0     1     0     0     0     0     0     0     0     0     0     0
依次类推,可以得到4的幂次皇后的一种放置方式,不过值得注意的是:2、3、8、9、14、15、26、27、38、39这10个N值不能采用这种分治法。
由4皇后直接推出16皇后的Matlab实现如下:

  1. clear all
  2. clc
  3.  
  4. a4=[ 0 0 1 0
  5. 1 0 0 0
  6. 0 0 0 1
  7. 0 1 0 0]
  8. [asize bsize]=size(a4);
  9.  
  10. a16=zeros(asize^2,bsize^2);
  11. [rowIndex,colIndex]=find(a4);
  12.  
  13. for i=1:length(rowIndex)
  14. a16((1+asize*(rowIndex(i)-1)):asize*rowIndex(i),(1+asize*(colIndex(i)-1)):asize*colIndex(i))=a4;
  15. end
  16. a16

运行结果如下:

原文:http://blog.csdn.net/tengweitw/article/details/44648249

作者:nineheadedbird

【算法导论】八皇后问题的算法实现(C、MATLAB、Python版)的更多相关文章

  1. 【算法】八皇后问题 Python实现

    [八皇后问题] 问题: 国际象棋棋盘是8 * 8的方格,每个方格里放一个棋子.皇后这种棋子可以攻击同一行或者同一列或者斜线(左上左下右上右下四个方向)上的棋子.在一个棋盘上如果要放八个皇后,使得她们互 ...

  2. Java实现蓝桥杯 算法提高 八皇后 改

    **算法提高 8皇后·改** 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 规则同8皇后问题,但是棋盘上每格都有一个数字,要求八皇后所在格子数字之和最大. 输入格式 一个8*8的棋 ...

  3. 一道算法题-八皇后问题(C++实现)

    八皇后问题 一.题意解析 国际象棋中的皇后,可以横向.纵向.斜向移动.如何在一个8X8的棋盘上放置8个皇后,使得任意两个皇后都不在同一条横线.竖线.斜线方向上?八皇后问题是一个古老的问题,于1848年 ...

  4. 算法学习 八皇后问题的递归实现 java版 回溯思想

    1.问题描述 八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行.纵行或 ...

  5. 八皇后问题-recall算法

    #!/usr/bin/env python3# -*- coding: utf-8 -*-import numbersimport numpyimport math'''八皇后为题:在国际象棋棋盘上摆 ...

  6. 【算法导论C++代码】Strassen算法

    简单方阵矩乘法 SQUARE-MATRIX-MULTIPLY(A,B) n = A.rows let C be a new n*n natrix to n to n cij = to n cij=ci ...

  7. 【算法导论】--分治策略Strassen算法(运用下标运算)【c++】

    由于偷懒不想用泛型,所以直接用了整型来写了一份 ①首先你得有一个矩阵的class Matrix ②Matrix为了方便用下标进行运算, Matrix的结构如图:(我知道我的字丑...) Matrix. ...

  8. C语言:试探算法解决“八皇后”问题

    #include <stdio.h> #define N 4 int solution[N], j, k, count, sols; int place(int row, int col) ...

  9. [算法导论]红黑树实现(插入和删除) @ Python

    class RBTree: def __init__(self): self.nil = RBTreeNode(0) self.root = self.nil class RBTreeNode: de ...

随机推荐

  1. Android开发之Path类使用详解,自绘各种各样的图形!

    玩过自定义View的小伙伴都知道,在View的绘制过程中,有一个类叫做Path,Path可以帮助我们实现很多自定义形状的View,特别是配合xfermode属性来使用的时候.OK,那我们今天就来看看P ...

  2. named let 递归和闭包的利器

    named let和递归,闭包联系十分密切.而且还是提高性能的重要手段.先来看一个make-list函数的模拟,最原始的写法大概是: (define (imake-list n member) ( n ...

  3. 重写方法的利器-super

    重写方法的利器-super class ilist(list): def __init__(self,dft=None,r=list()): super(ilist, self).__init__(r ...

  4. Android fragment(片段)构建灵活的UI

    在以支持多种屏幕尺寸为目标设计应用时,您可以在不同的布局配置中重复使用您的fragment 从而根据可用的屏幕空间优化用户体验. 例如,在手机设备上,由于采用单窗格用户界面,因此可能更适合一次只显示一 ...

  5. Cocos2D中节点Z序的计算规则

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交 ...

  6. android 获取SD卡的图片及其路径

    1.首先是intent的设置: private static final int IMAGECODE = 0; Intent imageIntent = new Intent(Intent.ACYIO ...

  7. UNIX网络编程——tcp流协议产生的粘包问题和解决方案

    我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...

  8. Tomcat集群应用部署的实现机制

    集群应用部署是一个很重要的应用场景,设想一下如果没有集群应用部署功能,每当我们发布应用时都要登陆每台机器对每个tomcat实例进行部署,这些工作量都是繁杂且重复的,而对于进步青年的程序员来说是不能容忍 ...

  9. Centos中git的安装

     CentOS的yum源中没有git,只能自己编译安装,现在记录下编译安装的内容,留给自己备忘. 确保已安装了依赖的包 yum install curl yum install curl-deve ...

  10. 后端分布式系列:分布式存储-MySQL 数据库事务与复制

    好久没有写技术文章了,因为一直在思考 「后端分布式」这个系列到底怎么写才合适.最近基本想清楚了,「后端分布式」包括「分布式存储」和 「分布式计算」两大类.结合实际工作中碰到的问题,以寻找答案的方式来剖 ...