Java解决棋盘覆盖问题
问题描述:
在一个2^k×2^k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
分析:
该题关键在于如何划分各L型骨牌所在位置区域。我们发现,L型骨牌占三个方格,我们可以把棋盘从中央分为四块,那么这四块子棋盘中仅一块是有特殊方格的,可以用一块骨牌使得其他三块子棋盘均被覆盖。以此为原则,无论这种分法是否最终可解,我们首先保证了每个子棋盘都有一个特殊方格,所以,分治的模型就出来了。
我们可以用递归来完成分治的任务。每次递归divide(zx,zy,si,x,y),(zx,zy)为子棋盘左上角坐标,si为子棋盘大小,因为棋盘总为正方形,所以si为边长,那么前3个参数就确定了子棋盘的位置和大小;(x,y)表示子棋盘中特殊方格的位置,这个位置是由上层递归分配骨牌后决定的。以此为标准。
递归流程为:
①判断边界,若当前棋盘大小为1,则无法再分割,递归结束。
②定子棋盘中心位置。
③判断特殊方格所在位置(左上,右上,左下,或右下)。
④根据特殊方格位置确定所选L型骨牌,原特殊方格和三个L型骨牌的方格分别为四个子棋盘的特殊方格。
⑤依据④中判断,按编号填充棋盘。
⑥4次递归,分别对应四个子棋盘。
算法实现:
(1)棋盘:可以用一个二维数组board[size][size]表示一个棋盘,其中,size=2^k。为了在递归处理的过程中使用同一个棋盘,将数组board设为全局变量;
(2)子棋盘:整个棋盘用二维数组board[size][size]表示,其中的子棋盘由棋盘左上角的下标tr、tc和棋盘大小s表示;
(3)特殊方格:用board[dr][dc]表示特殊方格,dr和dc是该特殊方格在二维数组board中的下标;
(4) L型骨牌:一个2^k×2^k的棋盘中有一个特殊方格,所以,用到L型骨牌的个数为(4^k-1)/3,将所有L型骨牌从1开始连续编号,用一个全局变量t表示。设全局变量t已初始化为0
下面讨论棋盘覆盖问题中数据结构的设计。
(1)棋盘:可以用一个二维数组board[size][size]表示一个棋盘,其中,size=2^k。为了在递归处理的过程中使用同一个棋盘,将数组board设为全局变量;
(2)子棋盘:整个棋盘用二维数组board[size][size]表示,其中的子棋盘由棋盘左上角的下标tr、tc和棋盘大小s表示;
(3)特殊方格:用board[dr][dc]表示特殊方格,dr和dc是该特殊方格在二维数组board中的下标;
(4) L型骨牌:一个2^k×2^k的棋盘中有一个特殊方格,所以,用到L型骨牌的个数为(4^k-1)/3,将所有L型骨牌从1开始连续编号,用一个全局变量t表示。
设全局变量t已初始化为0
下面讨论棋盘覆盖问题中数据结构的设计。
(1)棋盘:可以用一个二维数组board[size][size]表示一个棋盘,其中,size=2^k。为了在递归处理的过程中使用同一个棋盘,将数组board设为全局变量;
(2)子棋盘:整个棋盘用二维数组board[size][size]表示,其中的子棋盘由棋盘左上角的下标tr、tc和棋盘大小s表示;
(3)特殊方格:用board[dr][dc]表示特殊方格,dr和dc是该特殊方格在二维数组board中的下标;
(4) L型骨牌:一个2^k×2^k的棋盘中有一个特殊方格,所以,用到L型骨牌的个数为(4^k-1)/3,将所有L型骨牌从1开始连续编号,用一个全局变量t表示。
设全局变量t已初始化为0.
程序清单如下:
package chessboard;
import java.util.Scanner;
/**
*
* @author Administrator
*/
public class Chessboard {
private static int boardsize=8;
public static int[][] board = new int[boardsize][boardsize];
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
Scanner input = new Scanner(System.in);
System.out.println("棋盘的大小为"+boardsize);
int[][] board = new int[boardsize][boardsize];
System.out.println("特殊块在棋盘中的行号是:");
int dr = input.nextInt();
System.out.println("特殊块在棋盘中的列号是:");
int dc = input.nextInt();
chessBoard(0,0,dr-1,dc-1,boardsize);
System.out.println("特殊块在棋盘中的位置是第"+dr+"行第"+dc+"列,覆盖后的棋盘:");
printboard();
}
public static int title = 0;
public static void chessBoard(int tr, int tc, int dr, int dc, int size)
{
if (size == 1) return;
int t = title++, // L型骨牌号
s = size/2; // 分割棋盘
// 覆盖左上角子棋盘
if (dr < tr + s && dc < tc + s)
// 特殊方格在此棋盘中
chessBoard(tr, tc, dr, dc, s);
else {// 此棋盘中无特殊方格
// 用 t 号L型骨牌覆盖右下角
board[tr + s - 1][tc + s - 1] = t;
// 覆盖其余方格
chessBoard(tr, tc, tr+s-1, tc+s-1, s);}
// 覆盖右上角子棋盘
if (dr < tr + s && dc >= tc + s)
// 特殊方格在此棋盘中
chessBoard(tr, tc+s, dr, dc, s);
else {// 此棋盘中无特殊方格
// 用 t 号L型骨牌覆盖左下角
board[tr + s - 1][tc + s] = t;
// 覆盖其余方格
chessBoard(tr,tc+s,tr+s-1,tc+s,s);}
// 覆盖左下角子棋盘
if (dr >= tr + s && dc < tc + s)
// 特殊方格在此棋盘中
chessBoard(tr+s, tc, dr, dc, s);
else {// 用 t 号L型骨牌覆盖右上角
board[tr + s][tc + s - 1] = t;
// 覆盖其余方格
chessBoard(tr+s,tc,tr+s,tc+s-1,s);}
// 覆盖右下角子棋盘
if (dr >= tr + s && dc >= tc + s)
// 特殊方格在此棋盘中
chessBoard(tr+s, tc+s, dr, dc, s);
else {// 用 t 号L型骨牌覆盖左上角
board[tr + s][tc + s] = t;
// 覆盖其余方格
chessBoard(tr+s,tc+s,tr+s,tc+s,s);}
}
public static void printboard(){
for(int i=0;i<boardsize;i++){
for(int j =0;j<boardsize;j++){
System.out.print(board[i][j]+"\t");
}
System.out.println('\n');
}
}
}
根据提示,输入特殊块的行和列,输出矩阵数组,程序正确运行。
- 在JAVA开发中的中文处理问题及解决办法
- Java 编程技术中汉字问题的分析及解决
- JAVA中文问题解决总结
- Java 编程技术中汉字问题的分析及解决
- java浮点运算精度问题的解决
- Java 编程技术中汉字问题的分析及解决
- Linux平台下Java处理图像发生 X11错误解决方法
- 基于java时区转换夏令时的问题及解决方法
- Java中文识别问题完全解决办法[二]
- Java 编程技术中汉字问题的分析及解决
- Java 中文问题的解决 mysql, oracle, servlet, jsp
- JAVA中文问题解决总结
- Java 编程技术中汉字问题的分析及解决(从根源上解决)
- “winjava.exe”病毒的一种解决办法
- Java 编程技术中汉字问题的分析及解决(从根源上解决) (转)
- JAVA中文比较问题的分析和解决
- Java 中文问题的解决 mysql, oracle, servlet, jsp
- Java 中文问题的解决 mysql, oracle, servlet, jsp
- Java 编程技术中汉字问题的分析及解决
- java-Dom4j 编码问题彻底解决