java数据结构之n皇后问题

n皇后问题:

每一行只能有一个皇后,每一列也只能有一个皇后,这个可以用col[edg] 数组来表示某一列是否已经有皇后;

对角线 / 有如下性质: 对于这种方向上经过同一条线的方格,其横(i) 纵(j)坐标的和都相等 i+j, 一共有2*n-1条这种对角线;

对角线\有如下性质:对于这种方向上经过同一条对角线的方格, 其横(i) 纵(j)坐标有如下关系:i - j + n - 1都相等, 一共有2*n条这种对角线。

 

运行:

8皇后一共有92种解决方案:
=====================0===================
Q    *    *    *    *    *    *    *    
*    *    *    *    Q    *    *    *    
*    *    *    *    *    *    *    Q    
*    *    *    *    *    Q    *    *    
*    *    Q    *    *    *    *    *    
*    *    *    *    *    *    Q    *    
*    Q    *    *    *    *    *    *    
*    *    *    Q    *    *    *    *    
=====================1===================
Q    *    *    *    *    *    *    *    
*    *    *    *    *    Q    *    *    
*    *    *    *    *    *    *    Q    
*    *    Q    *    *    *    *    *    
*    *    *    *    *    *    Q    *    
*    *    *    Q    *    *    *    *    
*    Q    *    *    *    *    *    *    
*    *    *    *    Q    *    *    *    
=====================2===================

...

代码:

package cn.agan.recursive;

import java.util.ArrayList;

/**
 * 回溯法解决八皇后问题:
 *
 */

public class EightQueens {
    public static void main(String[] args) {
        ChessBoard chessBoard = new ChessBoard(8);
        chessBoard.findSolution(0);
        chessBoard.printChess();
    }
}


class ChessBoard {
    private int edg; //棋盘的边,一般棋盘都是正方形的
    private ArrayList<ChessPoint[]> s;
    private int[] rows;
    private boolean[] col;
    private boolean[] dial1;
    private boolean[] dial2;

    public ChessBoard(int edg) {
        this.edg = edg;
        s = new ArrayList<>();
        rows = new int[edg];            //一个解决方案中,下标表示每一个皇后的第几行,值表示其列
        col = new boolean[edg];         // |
        dial1 = new boolean[2*edg - 1]; // /:对于这种方向上经过同一条线的方格,其横(i) 纵(j)坐标的和都相等 i+j
        dial2 = new boolean[2*edg - 1]; // \:对于这种方向上经过同一条对角线的方格, 其横(i) 纵(j)坐标有如下关系:i - j + n - 1
    }

    public void findSolution( int rowIndex) {
        if (rowIndex == edg) {
            //得到一种解决方案,保存下
            saveSolution(rows);
            return ;
        }
         for (int i = 0; i < edg; i++) {
             if (!col[i] && !dial1[i+rowIndex] && !dial2[i-rowIndex+edg-1]) {
                 rows[rowIndex] = i;
                 col[i] = true;
                 dial1[i+rowIndex] = true;
                 dial2[i-rowIndex+edg-1] = true;
                 findSolution(rowIndex+1);
                 col[i] = false;
                 dial1[i+rowIndex] = false;
                 dial2[i-rowIndex+edg-1] = false;
             }

        }
         return;
    }

    //保存一个成功的摆放
    public void saveSolution(int[] rows) {
        ChessPoint[] tmp = new ChessPoint[rows.length];
        for (int i = 0; i < rows.length; i++) {
            ChessPoint chessPoint = new ChessPoint(i, rows[i]);
            tmp[i] = chessPoint;
        }
        s.add(tmp);
    }

    //打印所有的解决方案
    public void printChess() {
        System.out.println("一共有"+s.size() +"种解决方案:");
        for (int k = 0; k < s.size(); k++) {
            System.out.println("====================="+k+"===================");
            ChessPoint[] ps = s.get(k);
            for (int i = 0;  i < edg; i++) {
                for (int j = 0; j < edg; j++) {
                    if (ps[i].i == i && ps[i].j == j) {
                        System.out.printf("Q\t");
                    } else {
                        System.out.printf("*\t");
                    }
                }
                System.out.println();
            }
        }

    }
}

class ChessPoint {
    int i;
    int j;

    public ChessPoint(int x, int y) {
        i = x;
        j = y;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值