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

八皇后问题,是一个古老而著名的问题,问题如下:

在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

上边是一个8*8的国际棋盘,可以看到棋盘中的每个格子都标有数字。每个数字都是两位,十位数字表示该格子所在的行,而个位数字表示该格子所在的列。

这样不难发现,处在同一行的两个格子其十位数相同,处在同一列的两个格子其个位数相同,处在同一斜线的两个格子有:|两个数字个位数的差|=|两个数字十位数的差|。

主要的三个限制条件明白了,接下来我们选择一种数据结构对“皇后”进行存储。很明显,我们可以选择二维数组。但是还可以选择一维数组。在这里我们选择一维数组。

为什么选择一维数组呢?

1.因为一行只放一个皇后,很符合我们一维数组的存放特性,即一个索引对应一个元素。

2.相对于二维数组,一位数组比较简单,更适合初学者。

我们以皇后所在的行标作为一位数组的索引,皇后所在的列标作为该索引对应的元素,例如arr[3]=5,代表第三行的皇后在第五列。

下边我们以python以及JAVA为例来解决这个问题。

num=0
def eight_queen(arr,finish_line=0):
    if finish_line == len(arr):                     #如果放置皇后成功的行数与数组中的元素个数一致(即棋盘的行数)则认为完成了一种摆法
        global num                                  #将上边定义的num定义为全局变量  这样才能在后边对其进行自加操作
        num+=1
        print("第%s种摆法:" % num)
        for i in range(8):
            print((i,arr[i]))
        return
        # break

    for stand in range(len(arr)):                   #对整个列进行扫描,将列标的标号赋值给数组中对应的元素
        arr[finish_line] = stand
        flag = True
        for line in range(finish_line):
            if arr[line] == stand or abs(arr[line]-stand) == finish_line-line:   #有皇后与当前放置的皇后处于同一列或同一斜线上
                flag = False
                # stand-=1
        if flag==True:
            eight_queen(arr,finish_line+1)
if __name__ == ‘__main__‘:
    eight_queen([None]*8)
    if num != 0:
        print("一共有%s种摆法" % num)
    else:
        print("无解")

对于初学者理解可能不是特别轻松,所以在这里我们总结一个的定式,再遇到此类问题时直接套用以下定式即可。下边再讲的相关问题我们就套用以下定式。

num=0   #全局变量代表方法的数量
def model(arr,finish_row=0):
    if finish_row == len(arr):                 #完成了一种方法
        global num
        num+=1
        return
    for x in range(循环边界):
        具体操作                            #对列表的需求操作
        flag = True
        for y in range(循环边界):                   #找不符合条件的要求
            if 找不符合要求的情况:
                flag = False
        if flag==True:                      #完成了一行摆放后递归调用
            model(arr,finish_row+1)  

if __name__ == ‘__main__‘:
    model()     #调用即可
    print(num)  #输出方法数  

我们再把它改写为JAVA版:

public class eigthqueen {
    public static int num =0;    //定义全局变量,表示摆法
    public static void main(String[] args) {
        int [] arr = new int[8];  //以八皇后为例,定义对应长度的列表
        int finish_row = 0;       //初始完成的行数
        equeen(arr,finish_row);
        System.out.println();
        System.out.printf("一共%d种摆法",num);
    }
     static void equeen(int arr[],int finish_row){
        boolean flag = true;
       if(finish_row==arr.length){
         num++;
         System.out.println();                    //初学java,比较笨的输出方式
         System.out.printf("第%d种摆法",num);
         System.out.println();
         for(int i=0;i<arr.length;i++){
             System.out.print("(");
             System.out.print(i);
             System.out.print(",");
             System.out.print(arr[i]);
             System.out.print(")");
         }
         return;
       }
       for(int col=0;col<arr.length;col++){
           arr[finish_row] = col;
           flag = true;
           for(int row=0;row<finish_row;row++){
               if((arr[row]==col)||(Math.abs(arr[row]-col)==finish_row-row)){ //有皇后与当前放置的皇后在同一列或统一斜线的情况
                   flag = false;
               }
           }
           if(flag==true){  //完成一行皇后的放置
               equeen(arr,finish_row+1);
           }
       }
    }
}

同样在JAVA中我们同样也可以总结定式:

public class eigthqueen {
    public static int num =0;    //定义全局变量,表示摆法
    public static void main(String[] args) {
        int [] arr = new int[8];  //以八皇后为例,定义对应长度的列表
        int finish_row = 0;       //初始完成的行数
        equeen(arr,finish_row);
        System.out.printf("一共%d种摆法",num);
    }

     static void equeen(int arr[],int finish_row){
        boolean flag = true;
       if(finish_row==arr.length){
         num++;
         return;
       }
       for(int col=0;col<arr.length;col++){
           具体操作                            //对列表的需求操作
           flag = true;
           for(int row=0;row<finish_row;row++){
               if(找不符合要求的情况){
                   flag = false;
               }
           }
           if(flag==true){       //完成一小步骤方法后递归
               equeen(arr,finish_row+1);
           }
       }
    }
}

接下来几篇我们要讲的马走日问题以及剪邮票等问题都可以套用这个定式来解决,这样就可以更加熟悉对这个定式的使用。

原文地址:https://www.cnblogs.com/daimaxiaocai/p/11912271.html

时间: 2024-12-07 05:31:54

八皇后问题——回溯法(python&&JAVA)的相关文章

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

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

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

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

八皇后(回溯法)

题目内容 n*n的矩阵,作为棋盘,放置n个皇后,且它们都无法攻击其他皇后,求出放置方法 皇后的攻击方式,沿行.列.对角线都可以攻击其它皇后 基本思想 使用回溯法(穷举法) 所有的回溯问题都是由三个步骤组成:choose.explore.unchoose 因此对每个问题需要知道: choose what?   对于这个问题,我们选择每个字符串 how to explore?对于这个问题,我们对剩余的字符串做同样的事情. unchoose           做相反的操作选择 回溯法步骤 1.Def

八皇后问题 回溯法

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Demo 8 { 9 class Program 10 { 11 static int num = 8;/*可以随意修改,num是多少解的就是几皇后问题*/ 12 static int[] arr = new int[8

八皇后,回溯与递归(Python实现)

八皇后,回溯与递归(Python实现) 八皇后问题是十九世纪著名的数学家高斯1850年提出 .以下为python语言的八皇后代码,摘自<Python基础教程>,代码相对于其他语言,来得短小且一次性可以打印出92种结果.同时可以扩展为九皇后,十皇后问题. 问题:在一个8*8棋盘上,每一行放置一个皇后旗子,且它们不冲突.冲突定义:同一列不能有两个皇后,每一个对角线也不能有两个皇后.当然,三个皇后也是不行的,四个也是不行的,凭你的智商应该可以理解吧. 解决方案:回溯与递归. 介绍: 1.回溯法 回溯

N皇后问题--回溯法 (循环递归)

N皇后问题 问题描述:N皇后问题是一个经典的问题,在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行.同一列.同一斜线上的皇后都会自动攻击) 思路 (回溯法,循环递归):0. 初始化棋盘(全部为0)1. 依次将第一列棋子置为12. 放完棋子执行横向,纵向,斜向的update,把不能放棋子的位置置为23. 从第二列棋子开始,递归执行4. 执行到最后一列,退出递归5. 执行第一列的第二个棋子 实现: var N = 4; Array.prototype.count = functi

八皇后,回溯与递归

python语句的八皇后代码,摘自<Python基础教程>,代码相对于其他语言,来得短小且一次性可以打印出92种结果.同时可以扩展为九皇后,十皇后问题. 问题:在一个8*8棋盘上,每一行放置一个皇后旗子,且它们不冲突.冲突定义:同一列不能有两个皇后,每一个对角线也不能有两个皇后.当然,三个皇后也是不行的,四个也是不行的,应该凭智商应该可以理解吧. 解决方案:回溯法和递归法 1 import random 2 3 def conflict(state,col): 4 row=len(state)