分治思想在Trimino拼图中的Java实现

近期学习《算法设计与分析基础 第二版》,学习到了分治法,被课后习题吸引了,即Trimino拼图问题。想了好久,都没有想到如何去分而治之。然后就是Google到了相关的PPT。一看就明白了。自己就用代码实现了下。理解思想后,代码实现挺容易的。

这个谜题实际上可以做成一个小益智游戏。

分治思想的关键就在于构造相同的子问题。这是这个思想核心看似简单,实则需要对问题的洞察力。看到的PPT核心图如下:

算法的源代码如下:

/**
 * @author shuaiguangying
 *	用分治法解决棋盘覆盖问题
 *  在2^n*2^n棋盘里面有一个坏点
 *  坏点可以在任何位置
 *  用L型板块覆盖棋盘
 *  
 *  解决这个问题的关键在于:分治
 *  分治的关键在于来构造有坏点的棋盘
 *  
 */
public class Tromino {
	static int numOfL = 2;
	/**
	 * @param a 棋盘
	 * @param x 子棋盘的起始位置
	 * @param y 子棋盘的起始位置
	 * @param size 子棋盘的尺寸
	 * @param bx 子棋盘中坏点的位置
	 * @param by 子棋盘中坏点的位置
	 */
	public static void trimino(Integer[][] a,int x,int y,int size,int bx,int by){
		//把一个大图分为4个小图
		int nx =x+size/2,ny =y+size/2;//十字中心
		int[] bx4 = {nx  ,nx-1,nx-1,nx};
		int[] by4 = {ny-1,ny-1,ny  ,ny};
		if(by<ny&&bx>=nx){ //坏点在第一象限
			bx4[0]=bx;by4[0]=by;
		}else if(by<ny&&bx<nx){//坏点在第二象限
			bx4[1]=bx;by4[1]=by;
		}else if(by>=ny&&bx<nx){//坏点在第三象限
			bx4[2]=bx;by4[2]=by;
		}else{//坏点在第四象限
			bx4[3]=bx;by4[3]=by;
		}
		//把L形方块图到棋盘中
		for(int i=0;i<4;i++){
			if(by4[i]==by && bx4[i]==bx)continue;
			a[by4[i]][bx4[i]]=numOfL;
		}
		numOfL++;
		//分治 递归处理子问题
		if(size>2){
			trimino(a,nx,y,size/2,bx4[0],by4[0]);
			trimino(a,x,y,size/2,bx4[1],by4[1]);
			trimino(a,x,ny,size/2,bx4[2],by4[2]);
			trimino(a,nx,ny,size/2,bx4[3],by4[3]);
		}
	}
	public static void main(String[] args) {
		int size = 8;
		Integer[][] a=new Integer[size][size];
		int bx=7,by=1;a[by][bx]=1;
		trimino(a,0,0,size,bx,by);

		draw(a,size);
	}

	private static void draw(Integer[][] a,int size){
		JFrame f = new JFrame("trimino");

		Integer[] head = new Integer[size];
		for (int i=0;i<head.length;i++) head[i] = i+1;
		final Color[] color =new Color[22];
		for(int i=0;i<color.length;i++){
			int r = (int) ((Math.random()*10000)%255); 
			int b =(int) ((Math.random()*1000)%255); 
			int k =(int) ((Math.random()*10000)%255); 
			color[i] = new Color(r,b,k);
		}

		JTable table = new JTable(a,head);
		for (int i = 0; i < table.getColumnCount(); i++) {
			TableColumn column = table.getColumn(String.valueOf(i+1));
			column.setCellRenderer(new DefaultTableCellRenderer(){
				@Override
				public Component getTableCellRendererComponent(JTable table,
						Object value, boolean isSelected, boolean hasFocus,
						int row, int column) {
					int val = (Integer)value;
					setBackground(color[val-1]);
					return super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
							row, column);
				}
			});
		}

		table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		table.setRowHeight(50);
		f.getContentPane().add(table.getTableHeader(),BorderLayout.NORTH);
		f.getContentPane().add(table,BorderLayout.CENTER);

		f.setVisible(true);
		f.setSize(500, 500);
	}
}

为了展示算法的效果,画了一个图:

时间: 2024-12-09 12:26:05

分治思想在Trimino拼图中的Java实现的相关文章

java编程思想第四版中net.mindview.util包下载,及源码简单导入使用

在java编程思想第四版中需要使用net.mindview.util包,大家可以直接到http://www.mindviewinc.com/TIJ4/CodeInstructions.html 去下载,并按照所在页面的操作进行操作.当然也可以直接我下载下面的链接,下载的直接是JAR包,可以直接导入并使用: net.mindview.util包:百度网盘:点击下载  密码: ggpi java编程思想第四版源码:百度网盘:点击下载  密码: ur3e 下面我简单的介绍一下源码在Eclipse中的导

Nashorn 在JDK 8中融合Java与JavaScript之力

从JDK 6开始,Java就已经捆绑了JavaScript引擎,该引擎基于Mozilla的Rhino.该特性允许开发人员将JavaScript代码嵌入到Java中,甚至从嵌入的JavaScript中调用Java.此外,它还提供了使用jrunscript从命令行运行JavaScript的能力.如果不需要非常好的性能,并且可以接受ECMAScript 3有限的功能集的话,那它相当不错了. 从JDK 8开始,Nashorn取代Rhino成为Java的嵌入式JavaScript引擎.Nashorn完全支

在Windows中实现Java调用DLL(转载)

本文提供调用本地 C 代码的 Java 代码示例,包括传递和返回某些常用的数据类型.本地方法包含在特定于平台的可执行文件中.就本文中的示例而言,本地方法包含在 Windows 32 位动态链接库 (DLL) 中. 不过我要提醒您,对 Java 外部的调用通常不能移植到其他平台上,在 applet 中还可能引发安全异常.实现本地代码将使您的 Java 应用程序无法通过 100% 纯 Java 测试.但是,如果必须执行本地调用,则要考虑几个准则: 将您的所有本地方法都封装在单个类中,这个类调用单个

经典算法宝典——分治思想(四)(1)

分治法(Divide and Conquer)的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的几个相似问题,以便各个击破,分而治之. 说明: 分治策略的应用很广,具体表现形式各异,比如:折半查找.合并排序.快速排序.二叉树遍历(先遍历左子树再遍历右子树).二叉排序树的查找等算法. 一.分治算法框架 1.算法设计思想 分治法求解问题的过程是,将整个问题分解成若干个小问题后分而治之.如果分解得到的子问题相对来说还太大,则可反复使用分治策略将这些子问题分成更小的同类型子问题,直至产生出方

分治思想--小测试(归并排序后续)

1 package cn.it; 2 3 import java.util.Arrays; 4 // 利用分治思想 实现 归并排序 5 public class Fz { 6 public static void main(String[] args) { 7 int a[]={1,2,3,4,5,6,8,7,3,4,9,0}; 8 int temp[] = new int[a.length]; 9 sortdiv(a, 0, a.length-1, temp); 10 System.out.p

Nashorn——在JDK 8中融合Java与JavaScript之力--转

原文地址:http://www.infoq.com/cn/articles/nashorn 从JDK 6开始,Java就已经捆绑了JavaScript引擎,该引擎基于Mozilla的Rhino.该特性允许开发人员将JavaScript代码嵌入到Java中,甚至从嵌入的JavaScript中调用Java.此外,它还提供了使用jrunscript从命令行运行JavaScript的能力.如果不需要非常好的性能,并且可以接受ECMAScript 3有限的功能集的话,那它相当不错了. 从JDK 8开始,N

Nashorn——在JDK 8中融合Java与JavaScript之力

从JDK 6开始,Java就已经捆绑了JavaScript引擎,该引擎基于Mozilla的Rhino.该特性允许开发人员将JavaScript代码嵌入到Java中,甚至从嵌入的JavaScript中调用Java.此外,它还提供了使用jrunscript从命令行运行JavaScript的能力.如果不需要非常好的性能,并且可以接受ECMAScript 3有限的功能集的话,那它相当不错了. 从JDK 8开始,Nashorn取代Rhino成为Java的嵌入式JavaScript引擎.Nashorn完全支

一次性弄懂到底什么叫做分治思想(含有大量经典例题,附带详细解析)

期末了,通过写博客的方式复习一下算法,把自己知道的全部写出来 分治:分而治之,把一个复杂的问题分解成很多规模较小的子问题,然后解决这些子问题,把解决的子问题合并起来,大问题就解决了 但是我们应该在什么时候用分治呢?这个问题也困扰了我很久,做题的时候就不知道用什么算法 能用分治法的基本特征: 1.问题缩小到一定规模容易解决 2.分解成的子问题是相同种类的子问题,即该问题具有最优子结构性质 3.分解而成的小问题在解决之后要可以合并 4.子问题是相互独立的,即子问题之间没有公共的子问题 第一条大多数问

java面试题全集(中)--Java Web和Web Service相关面试题

这部分主要是与Java Web和Web Service相关的面试题. 96.阐述Servlet和CGI的区别? 答:Servlet与CGI的区别在于Servlet处于服务器进程中,它通过多线程方式运行其service()方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于Servlet. 补充:Sun Microsystems公司在1996年发布Servlet技术就是为了和CGI进行竞争,Servlet是一个特殊的Java程