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