• [洛谷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
    ",tpx+1,tpy+1,1);
        	if(bpx==tpx&&bpy==tpy+1)printf("%d %d %d
    ",tpx+1,tpy,2);
        	if(bpx==tpx+1&&bpy==tpy)printf("%d %d %d
    ",tpx,tpy+1,3);
    		if(bpx==tpx+1&&bpy==tpy+1)printf("%d %d %d
    ",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
    ",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
    ",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
    ",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
    ",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

  • 相关阅读:
    微信小程序开发学习--页面事件和数据绑定
    检测小程序版本更新提示
    vue-cli脚手架
    链表中倒数第K个结点
    调整数组顺序使奇数位于偶数前面
    数值的整数次方(十二)
    二进制中1的个数(十一)
    覆盖矩形(十)
    变态跳台阶(九)
    跳台阶(八)
  • 原文地址:https://www.cnblogs.com/COLIN-LIGHTNING/p/8572620.html
Copyright © 2020-2023  润新知