【洛谷】P1228 地毯填补问题

洛谷P1228 地毯填补问题

相传在一个古老的阿拉伯国家里,有一座宫殿。宫殿里有个四四方方的格子迷宫,国王选择驸马的方法非常特殊,也非常简单:公主就站在其中一个方格子上,只要谁能用地毯将除公主站立的地方外的所有地方盖上,美丽漂亮聪慧的公主就是他的人了。公主这一个方格不能用地毯盖住,毯子的形状有所规定,只能有四种选择(如图):
在这里插入图片描述
并且每一方格只能用一层地毯,迷宫的大小为
2 k × 2 k 2^k\times2^k 2k×2k的方形。当然,也不能让公主无限制的在那儿等,对吧?由于你使用的是计算机,所以实现时间为 1s。

输入格式

输入文件共 2 行。

第一行:
k,即给定被填补迷宫的大小为 2 k × 2 k ( 0 ≤ k ≤ 10 ) 2^k\times2^k(0\leq k\leq 10) 2k×2k(0k10)

第二行:x,y,即给出公主所在方格的坐标(x,y)

输出格式

将迷宫填补完整的方案:每一补(行)为x y c(x,y 为毯子拐角的行坐标和列坐标, c 为使用毯子的形状,具体见上面的图,毯子形状分别用 1,2,3,4 表示,x,y,c 之间用一个空格隔开)。

输入#1:

3                          
3 3   

输出#2:

5 5 1
2 2 4
1 1 4
1 4 3
4 1 2
4 4 1
2 7 3
1 5 4
1 8 3
3 6 3
4 8 1
7 2 2
5 1 4
6 3 2
8 1 2
8 4 1
7 7 1
6 6 1
5 8 3
8 5 2
8 8 1

这个题居然没想出来。。涉及到一个矩形和一个点的问题,其实之前就有做过,在leetcode 双周赛14里有一道矩形里找一个点的题。可以想到分治,把矩形分成四块,点至多在一个区域里,其他三个区域的边界就一定可以铺一个L型瓷砖了。铺完之后,四个区域里各有一个点被占用了,所以可以继续分治这四块区域,代码见下,几个注意点:

  • 因为这里n都已经是二的倍数了,所以非常方便,每次都是除以2
  • 每次solve三个瓷砖占的区域的函数调用都是一样的,可以考虑写成宏简化代码
  • 其实这道题再不会看看样例输出也能想到分治,样例先铺55(中间),然后依次处理左上、右上、左下和右下了。
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
int n;
int x,y;
void solve(int x,int y,int a,int b,int l){
    if(l==1) return ;
    if(x<a+l/2&&y<b+l/2){
        printf("%d %d 1\n",a+l/2,b+l/2);
        solve(x,y,a,b,l/2);
        solve(a+l/2-1,b+l/2,a,b+l/2,l/2);
        solve(a+l/2,b+l/2-1,a+l/2,b,l/2);
        solve(a+l/2,b+l/2,a+l/2,b+l/2,l/2);
    }
    else if(x<a+l/2&&y>=b+l/2){
        printf("%d %d 2\n",a+l/2,b+l/2-1);
        solve(a+l/2-1,b+l/2-1,a,b,l/2);
        solve(x,y,a,b+l/2,l/2);
        solve(a+l/2,b+l/2-1,a+l/2,b,l/2);
        solve(a+l/2,b+l/2,a+l/2,b+l/2,l/2);
    }
    else if(x>=a+l/2&&y<b+l/2){
        printf("%d %d 3\n",a+l/2-1,b+l/2);
        solve(a+l/2-1,b+l/2-1,a,b,l/2);
        solve(a+l/2-1,b+l/2,a,b+l/2,l/2);
        solve(x,y,a+l/2,b,l/2);
        solve(a+l/2,b+l/2,a+l/2,b+l/2,l/2);
    }
    else{
        printf("%d %d 4\n",a+l/2-1,b+l/2-1);
        solve(a+l/2-1,b+l/2-1,a,b,l/2);
        solve(a+l/2-1,b+l/2,a,b+l/2,l/2);
        solve(a+l/2,b+l/2-1,a+l/2,b,l/2);
        solve(x,y,a+l/2,b+l/2,l/2);
    }
}
int main()
{
    cin>>n;
    cin>>x>>y;
    solve(x,y,1,1,pow(2,n));
    return 0;
}

你可能感兴趣的:(洛谷,分治)