HUNAN 10432 棋盘覆盖问题

棋盘覆盖问题
Time Limit: 1000ms, Special Time Limit:2500ms,Memory Limit:32768KB
Total submit users: 65, Accepted users:26
Problem 10432 : No special judgement
Problem description
  在一个2k x 2k ( 即:2^k x 2^k )个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2L型骨牌不得重叠覆盖。


Input
  输入文件第一行是一个整数T,表示有多少组测试数据,接下来是T组测试数据,共2T行,每组第一行为整数n,2n次幂(1<=n<=64),表示棋盘的大小为n*n,第二行是两个整数,代表特殊方格所在行号和列号。
Output
  先输出“CASE:i,然后按样例输出。数据间用制表符隔开(‘t’),每行最后一个数据后无制表符。
Sample Input
2
2
0 0
8
2 2
Sample Output
CASE:1
0       1
1       1
CASE:2
3       3       4       4       8       8       9       9
3       2       2       4       8       7       7       9
5       2       0       6       10      10      7       11
5       5       6       6       1       10      11      11
13      13      14      1       1       18      19      19
13      12      14      14      18      18      17      19
15      12      12      16      20      17      17      21
15      15      16      16      20      20      21      21
Judge Tips
  要求遍历顺序按从左到右,从上到下。
Problem Source
  qshj
package hunan;

import java.util.Arrays;
import java.util.Scanner;
/**
 * @description							HUNAN OJ 10432 棋盘覆盖问题
 * @technique							递归分治
 * @version 							1.0
 * @date								20120821
 * @time								09:47
 * @author 								Alex
 * @note							    程序运行正确,但是提交不上去。查了好久,还是不行,最后果断放弃了。
 * 										先放这吧。有时间再看。
 */
public class HuNan10432_20120820_0 {
	private static int num = 1;   //记录填充的次数。
	private static int initX;    //特殊点 x 坐标。
	private static int initY;    //特殊点 x 坐标。
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int [][] map;
		int count, n, cas = 0;
		count = in.nextInt();
		while(count-->0){
			n = in.nextInt();
			num = 1;
			initX = in.nextInt();
			initY = in.nextInt();
			map = new int[n][n];
			init(map);
			map[initX][initY] = 0;
			solve(map, 0, 0, map.length, map.length,initX,initY);
			System.out.println("CASE:" + (++cas));
			show(map);
		}
	}
	/**
	 * 
	 * @param map  棋盘。
	 * @param i  棋盘左上角 x 坐标
	 * @param j  棋盘左上角 y 坐标
	 * @param x    棋盘右下角 x 坐标
	 * @param y    棋盘右下角 y 坐标
	 * @param initX		特殊点 x 坐标。
	 * @param initY     特殊点 x 坐标。
	 * @note	程序还没进行优化。好多重复代码。今天太累。不管了。
	 */
	private static void solve(int [][] map, int i, int j, int x, int y, int initX, int initY){
		if(i==x-1&&j==y-1){   //递归结束条件。 当棋盘只剩一个方格时束。
			return;
		}
		int i1,i2,i3,i4,j1,j2,j3,j4,x1,x2,x3,x4,y1,y2,y3,y4;
		i1 = i;j1 = j;x1 = (x+i)>>1;y1 = (y+j)>>1;  //左上角。
		i2 = i;j2 = (y+j)>>1; x2 = (x+i)>>1; y2 = y;  //右上角。
		i3 = (x+i)>>1; j3 = j; x3 = x; y3 = (y+j)>>1; //左下角。
		i4 = x1; j4 = y1; x4 = x; y4 = y;//右下角。
		if(isIn(i1,j1,x1,y1,initX,initY)){  //判断特殊点是否在左上角区域
			 map[x2-1][j2] = num; //右上。 //填充。
			 map[i4][j4] = num;//右下。
			 map[i3][y3-1] = num; //左下。
			 ++num;
			 solve(map,i1,j1,x1,y1,initX,initY);//如果在左上角。刚特殊点坐标不变。
			 solve(map,i2,j2,x2,y2,x2-1,j2);   //右上角特殊点坐标更新为刚刚在这一区域填充的点。
			 solve(map,i3,j3,x3,y3,i3,y3-1);	//同上。
			 solve(map,i4,j4,x4,y4,i4,j4);		//同上。
		}else if(isIn(i2,j2,x2,y2,initX,initY)){  判断特殊点是否在右上角区域
			 map[x1-1][y1-1] = num; //左上。
			 map[i4][j4] = num;//右下。
			 map[i3][y3-1] = num; //左下。
			 ++num;
			 solve(map,i1,j1,x1,y1,x1-1,y1-1);
			 solve(map,i2,j2,x2,y2,initX,initY);
			 solve(map,i3,j3,x3,y3,i3,y3-1);
			 solve(map,i4,j4,x4,y4,i4,j4);
		}else if(isIn(i3,j3,x3,y3,initX,initY)){  //判断特殊点是否在左下角区域
			 map[x2-1][j2] = num; //右上。
			 map[i4][j4] = num;//右下。
			 map[x1-1][y1-1] = num; //左上。
			 ++num;
			 solve(map,i1,j1,x1,y1,x1-1,y1-1);
			 solve(map,i2,j2,x2,y2,x2-1,j2);
			 solve(map,i3,j3,x3,y3,initX,initY);
			 solve(map,i4,j4,x4,y4,i4,j4);
		}else if(isIn(i4,j4,x4,y4,initX,initY)){  //判断特殊点是否在右下角区域
			map[x1-1][y1-1] = num; //左上。
			 map[i3][y3-1] = num; //左下。
			 map[x2-1][j2] = num; //右上。
			 ++num;
			 solve(map,i1,j1,x1,y1,x1-1,y1-1);
			 solve(map,i2,j2,x2,y2,x2-1,j2);
			 solve(map,i3,j3,x3,y3,i3,y3-1);
			 solve(map,i4,j4,x4,y4,initX,initY);
		}
	}
	
	/**
	 * 
	 * @param i	棋盘左上角 x 坐标
	 * @param j	棋盘左上角 y 坐标
	 * @param x 棋盘右下角 x 坐标
	 * @param y 棋盘右下角 y 坐标
	 * @param initX  特殊点 x 坐标。
	 * @param initY  特殊点 y 坐标。
	 * @return 如果特殊点在棋盘区域内,返回 true ,否则返回 false;
	 */
	private static boolean isIn(int i, int j, int x, int y, int initX, int initY){
		if(initX>=i && initY>=j && initX<x && initY<y){
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 初始化函数。 
	 * @param array
	 */
	private static void init(int [][] array){
		int i,len = array.length;
		for(i = 0; i < len; ++i){
			Arrays.fill(array[i], -1);
		}
	}
	private static void show(int [][] map){
		int i,j;
		for(i = 0; i < map.length; ++i){
			for(j = 0; j < map[i].length-1; ++j){
				System.out.print(map[i][j] + "\t");
			}
			System.out.println(map[i][j]);
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值