题目要求:
在一个 2 k ∗ 2 k ( k ≥ 0 ) 2^k*2^k(k≥0) 2k∗2k(k≥0) 个方格组成的棋盘中,恰有一-个方格与其他方格不同,称该方格为特殊方格。显然,特殊方格在棋盘中可能出现的位置有 4 k 4^k 4k种,因而有 4 k 4^k 4k种不同的棋盘。棋盘覆盖问题要求用4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
解题思路:
k=0 ,不需要填充
k = 1,填充1个骨牌
k = 2,填充41+1
k = 3,填充4(5)+1
…
k = n
显然是一个由上到下递归的过程,所以使用分治的思想解题
骨牌填充的过程:
在一个22区域中,必须需要一个特殊方格,才能够利用骨牌将其填充。
在一个44区域中,可以将其划分为四个区域,若特殊方格存在于左上区域,那么其余三个区域均不含特殊方格,不能够利用骨牌将其填充,所以需要利用一块L形骨牌,使其余三个区域都能获得“一块新增的特殊方格”。
以此类推,在
2
k
2^k
2k*
2
k
2^k
2k也是相同处理方式
代码实现
package com.算法.part01分治回溯;/*
* 作用:棋盘覆盖
*
*@author hby_gd@163.com
*@date 20/7/2020 上午2:04
*/
import java.util.Scanner;
public class ChessBoardCover {
private static int DEFAULT_LENGTH = 8;
private static int[][] board = new int[DEFAULT_LENGTH][DEFAULT_LENGTH];
private static int num = 1;
public static void main(String[] args) {
System.out.println("棋盘尺寸为:"+DEFAULT_LENGTH);
Scanner scanner = new Scanner(System.in);
System.out.println("请输入特殊棋子的行数");
int dr = scanner.nextInt();
System.out.println("请输入特殊棋子的列数");
int dc = scanner.nextInt();
//添加骨牌
processBoard(0,0,dr-1,dc-1,8);
//打印棋盘
printBoard();
}
private static void processBoard(int r0, int c0, int dr, int dc, int len) {
//递归边界
if(len == 1){
return;
}
int newLen = len/2;
int n = num++;
//对A区域作出处理
if(dr<r0+newLen&&dc<c0+newLen){
processBoard(r0,c0,dr,dc,newLen);
}else{
//将A区域右下角设为特殊方块
board[r0+newLen-1][c0+newLen-1] = n;
processBoard(r0,c0,r0+newLen-1,c0+newLen-1,newLen);
}
//对B区域作出处理
if(dr<r0+newLen&&dc>=c0+newLen){
processBoard(r0,c0+newLen,dr,dc,newLen);
}else{
//将B区域左下角设为特殊方块
board[r0+newLen-1][c0+newLen] = n;
processBoard(r0,c0+newLen,r0+newLen-1,c0+newLen,newLen);
}
//对C区域作出处理
if(dr>=r0+newLen&&dc<c0+newLen){
processBoard(r0+newLen,c0,dr,dc,newLen);
}else{
//将C区域右上角设为特殊方格
board[r0+newLen][c0+newLen-1] = n;
processBoard(r0+newLen,c0,r0+newLen,c0+newLen-1,newLen);
}
//对D区域作出处理
if(dr>=r0+newLen&&dc>=c0+newLen){
processBoard(r0+newLen,c0+newLen,dr,dc,newLen);
}else{
//将D区域左上角设为特殊方格
board[r0+newLen][c0+newLen] = n;
processBoard(r0+newLen,c0+newLen,r0+newLen,c0+newLen,newLen);
}
}
private static void printBoard() {
for (int i = 0; i < DEFAULT_LENGTH; i++) {
for (int j = 0; j < DEFAULT_LENGTH; j++) {
System.out.print(board[i][j]+" ");
}
System.out.println();
}
}
}
难点:
注意A,B,C,D四块区域的新的起点以及新的特殊方格位置的表示!