P1228 地毯填补问题(分治)
题目描述
相传在一个古老的阿拉伯国家里,有一座宫殿。宫殿里有个四四方方的格子迷宫,国王选择驸马的方法非常特殊,也非常简单:公主就站在其中一个方格子上,只要谁能用地毯将除公主站立的地方外的所有地方盖上,美丽漂亮聪慧的公主就是他的人了。公主这一个方格不能用地毯盖住,毯子的形状有所规定,只能有四种选择(如图):

并且每一方格只能用一层地毯,迷宫的大小为 2k×2k 的方形。当然,也不能让公主无限制的在那儿等,对吧?由于你使用的是计算机,所以实现时间为 1 秒。
输入格式
输入文件共 2 行。
第一行一个整数 k,即给定被填补迷宫的大小为 2k×2k(0<k≤10); 第二行两个整数 x,y,即给出公主所在方格的坐标(x 为行坐标,y 为列坐标),x 和 y 之间有一个空格隔开。
输出格式
将迷宫填补完整的方案:每一补(行)为 x y c(x,y 为毯子拐角的行坐标和列坐标,c 为使用毯子的形状,具体见上面的图 1,毯子形状分别用 1,2,3,4 表示,x,y,c 之间用一个空格隔开)。
package q2;
import java.util.*;public class Main {static StringBuilder res = new StringBuilder();public static void main(String[] args) {Scanner sc = new Scanner(System.in);int k = sc.nextInt();int n = 1 << k; // 棋盘大小 = 2^kint a = sc.nextInt();int b = sc.nextInt();f(1, 1, n, a, b);System.out.print(res.toString());}static void f(int x, int y, int size, int a, int b) {if (size == 1) return;int m = size / 2;  //将当前棋盘分割为4个子棋盘,每个子棋盘边长为m=size/2// 四个中心特殊格子位置int ltx = x + m - 1, lty = y + m - 1; // 左上int rtx = x + m - 1, rty = y + m;     // 右上int lbx = x + m,     lby = y + m - 1; // 左下int rbx = x + m,     rby = y + m;     // 右下// 判断特殊格在哪个象限if (a <= ltx && b <= lty) {        // 左上res.append(rbx + " " + rby + " 1\n");f(x, y, m, a, b);f(x, y + m, m, rtx, rty);f(x + m, y, m, lbx, lby);f(x + m, y + m, m, rbx, rby);} else if (a <= ltx && b > lty) {  // 右上res.append(lbx + " " + lby + " 2\n");f(x, y, m, ltx, lty);f(x, y + m, m, a, b);f(x + m, y, m, lbx, lby);f(x + m, y + m, m, rbx, rby);} else if (a > ltx && b <= lty) {  // 左下res.append(rtx + " " + rty + " 3\n");f(x, y, m, ltx, lty);f(x, y + m, m, rtx, rty);f(x + m, y, m, a, b);f(x + m, y + m, m, rbx, rby);} else {                           // 右下res.append(ltx + " " + lty + " 4\n");f(x, y, m, ltx, lty);f(x, y + m, m, rtx, rty);f(x + m, y, m, lbx, lby);f(x + m, y + m, m, a, b);}}
}
调用递归函数f(1,1,n,a,b),其中(1,1)是当前棋盘的左上角坐标,n=2^k是棋盘边长
递归函数f(x, y, size, a, b):
- (x, y)是当前棋盘的左上角坐标 
- size是当前棋盘的边长 
- (a, b)是特殊方格的坐标 
如果size==1,则直接返回,因为无法再分割。
将当前棋盘分割为4个子棋盘,每个子棋盘边长为m=size/2
判断特殊方格在哪个子棋盘:
- 如果在左上子棋盘(a<=ltx && b<=lty): 
 则在当前棋盘的中心位置(即另外三个子棋盘的相邻处)放置一个L型地毯,地毯的形状为1(即覆盖另外三个子棋盘的相邻方格)。
- 然后递归处理四个子棋盘: 
 左上子棋盘:特殊方格为原来的(a, b)
 右上子棋盘:特殊方格为(rtx, rty)(即右上子棋盘的左下角,也就是我们放置的地毯在右上子棋盘的那一个方格)
 左下子棋盘:特殊方格为(lbx, lby)(地毯在左下子棋盘的那一个方格)
 右下子棋盘:特殊方格为(rbx, rby)(地毯在右下子棋盘的那一个方格)
- 其他的类似 
为什么能这样做:
L 形地毯总是放置在四个子棋盘的交叉处,覆盖三个子棋盘各一个方格。这样,每个子棋盘在递归时都有一个特殊方格,保证了递归的可行性
