• N皇后问题


    八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

    算法思考,初步思路:

    构建二维int或者short型数组,内存中模拟棋盘

    chess[r][c]=0表示:r行c列没有皇后,chess[r][c]=1表示:r行c列位置有一个皇后

    从第一行第一列开始逐行摆放皇后

    依题意每行只能有一个皇后,遂逐行摆放,每行一个皇后即可

    摆放后立即调用一个验证函数(传递整个棋盘的数据),验证皇后摆放此处的合理性,安全则摆放下一个,不安全则尝试摆放这一行的下一个位置,直至摆到棋盘边界。当这一行所有位置都无法保证皇后安全时,需要回退到上一行,清除上一行的摆放记录,并且在上一行尝试摆放下一位置的皇后(回溯算法的核心)。

    当摆放到最后一行,并且调用验证函数确定安全后,累积数自增1,表示有一个解成功算出

    验证函数中,需要扫描当前摆放皇后的左上,中上,右上方向是否有其他皇后,有的话存在危险,没有则表示安全,并不需要考虑当前位置棋盘下方的安全性,因为下面的皇后还没有摆放。

    使用递归算法逐行摆放皇后,代码如下:

    package com.wyl;
    
    /**
     * 递归解决8皇后问题,8个皇后任意两个不能处于同一行,同一列及同一对角线上
     * 
     * @author wyl
     *
     */
    public class EightQueen {
        private static final int N = 4; // 8皇后,便于求解N皇后问题
        private static int count = 0; // 记录有多少中摆放可能
    
        public static void main(String[] args) {
            int[][] chess = new int[N][N]; // 初始化棋盘,chess[i][j] = 0 表示此处没有皇后,为1表示有皇后
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    chess[i][j] = 0;
                }
            }
            long start = System.currentTimeMillis();
            putQueenToChess(chess, 0); // 从第一行开始摆放皇后
            long end = System.currentTimeMillis();
            System.out.println("一共有: " + count + "中摆放方法,耗时: " + (end-start)+ "毫秒");
        }
    
        private static void putQueenToChess(int[][] chess, int row) {
            // TODO Auto-generated method stub
            if (row == N) { // 一次摆放已经完成
                count++;
                System.out.println("第 " + count + " 种解:");
                for (int i = 0; i < N; i++) {
                    for (int j = 0; j < N; j++) {
                        System.out.print(chess[i][j] + " ");
                    }
                    System.out.println();
                }
                return;
            }
            // 摆放第row行的皇后
            int[][] newArray = chess.clone(); // 复制已经摆放row-1行的棋盘
            
            // 摆放第row行的皇后
            for (int i = 0; i < N; i++) {
                // 将第row行清空
                for (int j = 0; j < N; j++) {
                    newArray[row][j] = 0;
                }
                newArray[row][i] = 1;
                if (isSafety(newArray, row, i)) { // 判断皇后放置位置是否合法
                    putQueenToChess(chess, row + 1); // 给下一行摆放皇后
                }
            }
        }
    
        /**
         * 判断皇后放置的位置是否合法 即只判断摆放位置的左上、中上、右上元素是否为1,
         * 并且同列上是否有皇后,对角线上是否有元素
         * @param newArray
         * @param row
         * @param i
         */
        private static boolean isSafety(int[][] chess, int row, int col) {
            // TODO Auto-generated method stub
            int step = 1; 
            while (row - step >= 0) {
                if (chess[row - step][col] == 1) { // 判断中上
                    return false;
                } else if (col - step >= 0 && chess[row - step][col - step] == 1) { // 左上
                    return false;
                } else if (col + step < N && chess[row - step][col + step] == 1) { // 右上
                    return false;
                }
                step++;
            }
            return true;
        }
    }
  • 相关阅读:
    POJ 2975 Nim
    分治法习题
    排序与查找习题
    查找
    SQL注入之Sqli-labs系列第二十五关(过滤 OR & AND)和第二十五A关(过滤逻辑运算符注释符)
    SQL注入之Sqli-labs系列第二十四关(二阶注入)
    SQL注入之Sqli-labs系列第二十三关(基于过滤的GET注入)
    SQL注入之Sqli-labs系列第二十一关(基于复杂性的cookie POST报错注入)和二十二关(基于双引号的cookie POST报错注入)
    SQL注入之Sqli-labs系列第二十关(基于头部的cookie POST报错注入)
    json csrf
  • 原文地址:https://www.cnblogs.com/studyDetail/p/7234907.html
Copyright © 2020-2023  润新知