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

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

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

C语言实现:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 8//棋盘大小

int matrix[N][N];//存储皇后的位置,其实也可以用一维数组表示

void PrintQueen();//打印棋盘
void PlaceQueen(int row);//放置皇后
int Conflict(int row,int col);//检查当前皇后是否与之前的冲突

int main()
{
    PlaceQueen(0);
    return 0;
}

void PrintQueen()
{
    static int solutionNum=0;//看总共有多少种情况
    solutionNum+=1;
    int row,col;
    printf("第%d种方法:\n",solutionNum);
    for(row=0;row<N;row+=1)
    {
        for(col=0;col<N;col+=1)
        {
            if(matrix[row][col])
            {
                printf("* ");
            }
            else
            {
                printf("- ");
            }
        }
        printf("\n");
    }
    printf("\n");
}

int Conflict(int row,int col)
{
	for (int m = 0; m <row ; m++)
	{
        for (int n = 0; n <N; n++)
		{
            if (matrix[m][n] == 1) //  每一行只有一个皇后
			{
                if ( n == col || abs(row - m) == abs(col - n) )   // 检查是否与之前的皇后冲突
                    return false;
            }
        }
    }
    return true;
}

void PlaceQueen(int row)
{
	if(row>=N)//已经放置了N个皇后
	{
		PrintQueen();
	}
	else
	{
		for(int col=0;col<N;col++)
		{
			matrix[row][col]=1;
			if(row==0||Conflict(row,col))
					PlaceQueen(row+1);//递归调用
			matrix[row][col]=0;
		}

	}

}

MATLAB实现

脚本文件Queen.m

 clear all
clc

global solutionNum;
solutionNum=0;%全局变量记录方法数
N=8;%皇后个数
matrix=zeros(N);%存储皇后位置信息

PlaceQueen(1,matrix,N)%调用放置方法

函数文件PlaceQueen.m

function PlaceQueen(row,matrix,N)%回溯法放置皇后

    if row>N
        PrintQueen(N,matrix);%打印棋盘
    else
        for col=1:N
            matrix(row,col)=1;
            if row==1||Conflict(row,col,N,matrix)%检测是否冲突
                PlaceQueen(row+1,matrix,N);
            end
            matrix(row,col)=0;
        end
    end

    %子函数:检测冲突
    function result=Conflict(row,col,N,matrix)%检测是否冲突

    result=1;
    for i=1:row-1
        for j=1:N
            if matrix(i,j)==1
                if ((j==col)||(abs(row-i)==abs(col-j)))%是否产生冲突:在同一直线,斜线上
                    result=0;
                    break;
                end
            end
        end
        if result==0
            break;
        end
    end

    %子函数:打印棋盘信息
function PrintQueen(N,matrix)

    global solutionNum; %定义全局变量,来累积方法数
    solutionNum=solutionNum+1;

    disp(['第',num2str(solutionNum),'种方法:'])

disp(matrix)

PYTHON实现:

def conflict(state,nextX):#冲突检测函数
    nextY=len(state)
    for i in range(nextY):
        if abs(state[i]-nextX) in (0,nextY-i):#检测是否在同一直线、斜线
            return True
    return False

def queens(num=8,state=()): #放置皇后,采用元组state来存储皇后的位置
    for pos in range(num):
        if not conflict(state,pos):
            if len(state)==num-1:
                yield (pos,)
            else:
                for result in queens(num,state+(pos,)):
                    yield (pos,)+result

for solution in queens(8):
    print (solution)

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实现如下:

clear all
clc

a4=[  0     0     1     0
     1     0     0     0
     0     0     0     1
     0     1     0     0]
 [asize bsize]=size(a4);

 a16=zeros(asize^2,bsize^2);
 [rowIndex,colIndex]=find(a4);

 for i=1:length(rowIndex)
     a16((1+asize*(rowIndex(i)-1)):asize*rowIndex(i),(1+asize*(colIndex(i)-1)):asize*colIndex(i))=a4;
 end
 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. Linux 中交换空间 (swap)应该分多大才好?

    前一段时间,我们机房中一台Linux服务器运行缓慢,系统服务出现间歇性停止响应,让我过去处理一下这一问题,登录到服务器之后,发现此服务器的物理内存是16G,而最初装机的时候,系统管理人员却只分配了4G ...

  2. 关于bitmap你不知道的一些事

    1.计算机表示图形的几种方式 1)BMP :几乎不进行压缩 占用空间比较大 2)JPG : 在BMP的基础上对相邻的像素进行压缩,占用空间比BMP小 3) PNG : 在JPG的基础上进一步压缩 占用 ...

  3. 有一台机器,上面有m个储存空间。然后有n个请求,第i个请求计算时需要占 R[i]个空间,储存计算结果则需要占据O[i]个空间(据O[i]个空间(其中O[i]<R[i])。问怎么安排这n个请求的顺序,使

    有一台机器,上面有m个储存空间.然后有n个请求,第i个请求计算时需要占 R[i]个空间,储存计算结果则需要占据O[i]个空间(据O[i]个空间(其中O[i]<R[i]).问怎么安排这n个请求的顺 ...

  4. java创建线程

    创建一个线程 Java提供了两种创建线程方法: 通过实现Runable接口: http://blog.csdn.net/duruiqi_fx/article/details/52187275 通过继承 ...

  5. Hexo写博客

    hexo配置github Git Install hexo-deployer-git. $ npm install hexo-deployer-git –save 配置_config.yml文件 de ...

  6. 剑指offer-面试题7:俩个栈实现队列(java)

    详细分析请参照C语言版,这里仅仅给出实现代码,注释很详细,不得不说java各种api用起来真是爽飞了 1 package com.xsf.SordForOffer; 2 3 import java.u ...

  7. SQL Server专家的10个秘诀(翻译加注解)

    当你点开这篇文章的时候,如果觉得没有读下去的必要,也希望你能拉到最后看看那几行字! 原文出处:https://technet.microsoft.com/en-us/magazine/gg299551 ...

  8. NewSQL数据库VoltDB特性简介

    VoltDB是一个革命性的新型数据库产品,被称作NewSQL数据库.它基于H-Store,号称比当前数据库产品的吞吐量高45倍,同时又具有很高的扩展性.它的特性主要有以下几点: Ø  高吞吐.低延迟: ...

  9. memcached实战系列(四)memcached stats命令 memcached优化

    memcached提供一系列的命令进行优化的查看,方便我们调整我们的存储策略,查看我们的使用率,内存的使用率以及浪费情况.常用的命令有stats.stats settings.stats items. ...

  10. 05 利用Appliction 传值Activity

    步骤一:新建一个类继承Application必须是public class 不然直接奔溃 步骤二:在清单文件AndroidManifest.xml的application添加name属性 值为com. ...