-
实验目的
如何应用分治法求解棋盘覆盖问题呢?分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格,从而将原问题分解为规模较小的棋盘覆盖问题。
-
实验内容
在一个2^k * 2^k个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为以特殊棋盘。在棋盘覆盖问题中,要用如下图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格之外的所有方格,且任何2个L型骨牌不得重叠覆盖。当k>0时,将2^k * 2^k棋盘分割为4个2^(k-1) * 2^(k - 1)子棋盘。特殊方格必位于4个较小子棋盘之一种,其余3个子棋盘中无特殊方格。为了将这3个无特殊方格的子棋盘转化为特殊棋盘,可以用一个L型骨牌覆盖这3个较小棋盘的会合处。从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种分割,直至棋盘简化为棋盘1*1。
- 关键代码记录
public class Chess {
/** 棋盘的规格 */
public static int SIZE = 8;
/** 特殊格子的竖坐标(从零开始) */
public static int TR = 6;
/** 特殊格子的横坐标(从零开始) */
public static int TC = 1;
/** 模拟棋盘 */
static int[][] board;
/** 模拟骨牌(相同数字为同一块骨牌) */
static int tile = 1;
/**
* 棋盘覆盖问题
* @param dr 左上角方格行号
* @param dc 左上角方格列号
* @param tr 特殊方格行号
* @param tc 特殊方格列号
* @param size 2的正整数次方
*/
public static void chessBoard(int dr, int dc, int tr, int tc, int size) {
if (size == 1) {
return;
}
int t = tile++;
/** 分割棋盘后的size */
int s = size / 2;
// 判断特殊方格是否在左上角的小棋盘中
if (tr < dr + s && tc < dc + s) {
chessBoard(dr, dc, tr, tc, s);
} else {
board[dr + s - 1][dc + s - 1] = t;
chessBoard(dr, dc, dr + s - 1, dc + s - 1, s);
}
// 判断特殊方格是否在右上角的小棋盘中
if (tr < dr + s && tc >= dc + s) {
chessBoard(dr, dc + s, tr, tc, s);
} else {
board[dr + s - 1][dc + s] = t;
chessBoard(dr, dc + s, dr + s - 1, dc + s, s);
}
// 判断特殊方格是否在左下角的小棋盘中
if (tr >= dr + s && tc < dc + s) {
chessBoard(dr + s, dc, tr, tc, s);
} else {
board[dr + s][dc + s - 1] = t;
chessBoard(dr + s, dc, dr + s, dc + s - 1, s);
}
// 判断特殊方格是否在youxia角的小棋盘中
if (tr >= dr + s && tc >= dc + s) {
chessBoard(dr + s, dc + s, tr, tc, s);
} else {
board[dr + s][dc + s] = t;
chessBoard(dr + s, dc + s, dr + s, dc + s, s);}}
public static void main(String[] args) {
// init parameter
try{
if(args[0]!=null){
SIZE = Integer.parseInt(args[0], 10);
}
if(args[1]!=null){
TR = Integer.parseInt(args[1], 10);
}
if(args[2]!=null){
TC = Integer.parseInt(args[2], 10);
}
}catch(Exception e){
System.out.print("\t采用默认参数");
}
System.out.printf("\t棋盘规模:%d*%d",SIZE,SIZE);
System.out.printf("\t特殊方格:(%d,%d)",TR,TC);
// 初始化棋盘
board = new int[SIZE][SIZE];
// 调用方法进行测试
chessBoard(0, 0, TR, TC, SIZE);
// 显示棋盘结果
for (int[] is : board) {
System.out.println();
for (int i : is) {
System.out.printf("%4d", i);
}
}
}