[洛谷P1228]地毯填补问题 题解(分治)

Description

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

并且每一方格只能用一层地毯,迷宫的大小为(2k)^2的方形。当然,也不能让公主无限制的在那儿等,对吧?由于你使用的是计算机,所以实现时间为1s。

输入格式:输入文件共2行。
第一行:k,即给定被填补迷宫的大小为2^k(0<k≤10);
第二行:x y,即给出公主所在方格的坐标(x为行坐标,y为列坐标),x和y之间有一个空格隔开。

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

Solution

1.经典的棋盘覆盖问题,考虑将问题化为小的子状态,分而治之;

2.首先对于一个棋盘,我们考虑把它等分成边长为原来一半的四个小棋盘,那么污点肯定在四个棋盘中的一个里,那么我们在分割点处,其他三个无污点的棋盘上,靠近分割点的格点上放上地毯,并递归处理四个小的棋盘;

3.在小的棋盘中,若原来污点就在其中,则按上述原则处理,若不在,则把上一层铺地毯的定点视为污点,按上述原则处理;

4.在传参时,若已经分割成边长等于2时,直接判断污点的位置,在另三个格子中铺同一块地毯即可;

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

inline int read(){
    int x=0;
    bool f=true;
    char c;
    c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=false;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return f?x:-x;
} 

void apart(int tpx,int tpy,int sz,int bpx,int bpy){
    if(sz==2){
    	if(bpx==tpx&&bpy==tpy)printf("%d %d %d\n",tpx+1,tpy+1,1);
    	if(bpx==tpx&&bpy==tpy+1)printf("%d %d %d\n",tpx+1,tpy,2);
    	if(bpx==tpx+1&&bpy==tpy)printf("%d %d %d\n",tpx,tpy+1,3);
		if(bpx==tpx+1&&bpy==tpy+1)printf("%d %d %d\n",tpx,tpy,4);
		return; 
	};
    int mid=sz/2;  //把区间划分成边长为原来一半的四个等面积矩形 
    //处理左上角的四分之一矩阵: 
    if(bpx<tpx+mid&&bpy<tpy+mid){
		apart(tpx,tpy,mid,bpx,bpy);
		printf("%d %d %d\n",tpx+mid,tpy+mid,1);
    }
	else apart(tpx,tpy,mid,tpx+mid-1,tpy+mid-1); 
    
    //处理左下角四分之一的矩阵:
    if(bpx<tpx+mid&&bpy>=tpy+mid){
    	apart(tpx,tpy+mid,mid,bpx,bpy);
		printf("%d %d %d\n",tpx+mid,tpy+mid-1,2);
	}
    else apart(tpx,tpy+mid,mid,tpx+mid-1,tpy+mid);

    //处理右上角四分之一的矩阵:
    if(bpx>=tpx+mid&&bpy<tpy+mid){
    	apart(tpx+mid,tpy,mid,bpx,bpy);
    	printf("%d %d %d\n",tpx+mid-1,tpy+mid,3);
    }
    else apart(tpx+mid,tpy,mid,tpx+mid,tpy+mid-1);

    //处理右下角四分之一的矩阵:
    if(bpx>=tpx+mid&&bpy>=tpy+mid){
    	apart(tpx+mid,tpy+mid,mid,bpx,bpy);
    	printf("%d %d %d\n",tpx+mid-1,tpy+mid-1,4);
	}
	else apart(tpx+mid,tpy+mid,mid,tpx+mid,tpy+mid);
}

int main(){
    int k,x,y,size=1;
    k=read();
    for(int i=1;i<=k;++i) size*=2;
    x=read();
    y=read();
    apart(1,1,size,x,y);
    return 0;
} 

关于棋盘覆盖问题更系统的讲解:https://wenku.baidu.com/view/e331f06c336c1eb91a375d75.html

关于棋盘覆盖问题推荐题目:https://www.luogu.org/problemnew/show/T24245

posted @ 2018-03-15 11:32  COLINGAO  阅读(742)  评论(0编辑  收藏  举报