0
点赞
收藏
分享

微信扫一扫

分治回溯算法----棋盘覆盖问题

大南瓜鸭 2022-01-21 阅读 93
算法java

棋盘覆盖问题:在一个2^k×2^k(k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。显然,特殊方格在棋盘中可能出现的位置有4^k种,因而有4^k种不同的棋盘。棋盘覆盖问题要求用4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。如图:以4*4的棋盘为例:

四种不同形状的L型骨牌:

骨牌覆盖的结果:

 

棋盘填充的实现:

//分治回溯 分治的应用 之 棋盘覆盖问题
/*
利用分治算法 将棋盘分成三个子棋盘
首先要先判断特殊方格在哪个子棋盘中
若特殊方格在左上子棋盘中 就继续向下递归 将子棋盘再分为四个子棋盘即可
若左上子棋盘中没有特殊方格 我们就将左上子棋盘中的右下方的格子 当成一个特殊方格
再继续向下递归 将子棋盘再分为四个子棋盘 直到棋盘被全部覆为止
若右上子棋盘中没有特殊方格 我们就将右上子棋盘中的左下方的格子 当成一个特殊方格
再继续向下递归 将子棋盘再分为四个子棋盘 直到棋盘被全部覆为止
若左下子棋盘中没有特殊方格 我们就将下上子棋盘中的右上方的格子 当成一个特殊方格
再继续向下递归 将子棋盘再分为四个子棋盘 直到棋盘被全部覆为止
若右下子棋盘中没有特殊方格 我们就将右下子棋盘中的左上方的格子 当成一个特殊方格
再继续向下递归 将子棋盘再分为四个子棋盘 直到棋盘被全部覆为止
 */
public class ChessboardCoverage {
    //表示棋盘尺寸
    private static int BOARD_SIZE = 8;
    //表示棋盘
    private static int[][] chess = new int[BOARD_SIZE][BOARD_SIZE];
    //骨牌编号 一层L型骨牌的编号要一直 0表示特殊方格
    private static int title = 0;
 
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入特殊格子在棋盘中的坐标:");
        int dr = input.nextInt(); //表示特殊格子在棋盘中的横坐标
        int dc = input.nextInt(); //表示特殊格子在棋盘中的纵坐标
 
        chessBoard(0, 0, dr, dc, BOARD_SIZE); //棋盘填充方法
 
        for(int i = 0; i < chess.length; i++){ //遍历输出棋盘
            for(int j = 0; j < chess.length; j++){
                System.out.print(chess[i][j] + "\t");
            }
            System.out.println();
        }
    }
 
    //棋盘填充方法
    //(tr, tc)表示棋盘或者子棋盘的对应起点坐标 (dr, dc)表示棋盘中特殊坐标的位置 size表示棋盘或子棋盘尺寸
    private static void chessBoard(int tr, int tc, int dr, int dc, int size) {
        if(size == 1){ //递归临界条件 当棋盘尺寸等于1时 返回
            return;
        }
        int s = size / 2; //表示棋盘或子棋盘尺寸 每次递归就除2 如将8*8的棋盘 分成四个4*4的子棋盘
        int num = ++title; //更新L型骨牌编号 同一层的骨牌编号应该一致
 
        //判断特殊坐标 在棋盘中的哪一部分子棋盘中
        //如果特殊方格在左上子棋盘中
        if(dr < tr + s && dc < tc + s){
            chessBoard(tr, tc, dr, dc, s); //向下递归chessBoard方法 更新子方格起始位置和特殊方格位置
        }else{ //如果特殊方格不在左上子棋盘中
            chess[tr + s - 1][tc + s - 1] = num; //就规定左上角子棋盘中的右下角方格为特殊方格 将编号写入特殊方格
            chessBoard(tr, tc, tr + s - 1, tc + s - 1, s);//向下递归chessBoard方法 更新子方格起始位置和特殊方格位置
        }
 
        //如果特殊方格在右上子棋盘
        if(dr >= tr + s && dc < tc + s) {
            chessBoard(tr + s, tc, dr, dc, s); //向下递归chessBoard方法 更新子方格起始位置和特殊方格位置
        }else{ //如果特殊方格不在右上子棋盘中
            chess[tr + s][tc + s - 1] = num; //就规定右上角子棋盘中的左下角方格为特殊方格 将编号写入特殊方格
            chessBoard(tr + s, tc, tr + s,tc + s - 1, s); //向下递归chessBoard方法 更新子方格起始位置和特殊方格位置
        }
 
        //如果特殊方格在左下子棋盘
        if(dr < tr + s && dc >= tc + s){
            chessBoard(tr, tc + s, dr, dc, s); //向下递归chessBoard方法 更新子方格起始位置和特殊方格位置
        }else{ //如果特殊方格不在左下子棋盘中
            chess[tr + s - 1][tc + s] = num; //就规定左下角子棋盘中的右上角方格为特殊方格 将编号写入特殊方格
            chessBoard(tr, tc + s, tr + s - 1, tc + s, s); //向下递归chessBoard方法 更新子方格起始位置和特殊方格位置
        }
 
        //如果特殊方格在右下子棋盘
        if(dr >= tr + s && dc >=tc + s){
            chessBoard(tr + s, tc + s, dr, dc, s); //向下递归chessBoard方法 更新子方格起始位置和特殊方格位置
        }else{  //如果特殊方格不在右下子棋盘中
            chess[tr + s][tc + s] = num; //就规定右下角子棋盘中的左上角方格为特殊方格 将编号写入特殊方格
            chessBoard(tr + s, tc + s, tr + s, tc + s, s); //向下递归chessBoard方法 更新子方格起始位置和特殊方格位置
        }
    }
}

棋盘填充的结果为:

 

 

举报

相关推荐

0 条评论