P1228 地毯填补问题
题目链接 https://www.luogu.com.cn/problem/P1228
这题一上来让我很摸不着头脑啊............
好不容易摸着了写的时候又迷糊了........
好不容易写完了结果传参数传不对........
好不容易传对了提交7遍都WA了...........
找了半天bug发现没加空格....................
分治+递归(递的我属实有点儿迷糊啊...)
题目说啦,只要你能用“地毯将除公主站立的地方外的所有地方盖上”,你就能拥有到美丽漂亮聪慧的公主!
所以说,不管一共有几种方法,只要用一种方式盖上就好啦。
那么面对210×210这么大的宫殿,一定有某种规律让我们能解决它。
ready?go!
当n=1时,无论公主在哪一个格子,我们都可以用一块地毯盖满。
当n=2时,分解成四个n=1时的格子。
当n=3时,分解成四个n=2时的格子。
……(以此类推)
由此我们可以看出,这题得用递归。
可是当n=2时是可以分解成四个n=1时的格子啊,没有公主我也没办法用一块地毯盖满啊?
童话故事里总会有假公主的出现。我们可以在中间的四个格子选择三个,先铺一块地毯,每一个格子的地毯作为一个“假公主”,这样不就使每个2×2的格子上有一位公主了吗。
注意,在中间添加的地毯的缺口应指向公主。如下图:
当n=3时:
以此类推,2k×2k的情况总能分解成4个2k-1×2k-1的情况,直到k=2。
步骤大致为:找到真公主所在方位,在方格中间填补地毯(假公主),这时每个被分划好的区域都有一个公主(真或假),开始递归。
放AC代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ul dfs(t,a,b,a+t-1,b+t-1)//向左上递归 4 #define ur dfs(t,a,b+t,a+t-1,b+t)//向右上递归 5 #define dl dfs(t,a+t,b,a+t,b+t-1)//向左下递归 6 #define dr dfs(t,a+t,b+t,a+t,b+t)//向右下递归 7 int n,x,y; 8 void dfs(int t,int a,int b,int x,int y) 9 //t表示此次要填的迷宫的大小 10 //a、b表示此迷宫左上角的位置 11 //x、y表示公主所在位置(或假公主的位置) 12 { 13 if(t==1) return; 14 t>>=1;//t/2,缩小迷宫范围 15 if(x-a<t&&y-b<t)//缺口在左上角 16 { 17 cout<<a+t<<' '<<b+t<<' '<<1<<endl; 18 dfs(t,a,b,x,y); 19 ur; dl; dr; 20 } 21 if(x-a<t&&y-b>=t)//在右上角 22 { 23 cout<<a+t<<' '<<b+t-1<<' '<<2<<endl; 24 dfs(t,a,b+t,x,y); 25 ul; dl; dr; 26 } 27 if(x-a>=t&&y-b<t)//左下角 28 { 29 cout<<a+t-1<<' '<<b+t<<' '<<3<<endl; 30 dfs(t,a+t,b,x,y); 31 ul; ur; dr; 32 } 33 if(x-a>=t&&y-b>=t)//右下 34 { 35 cout<<a+t-1<<' '<<b+t-1<<' '<<4<<endl; 36 dfs(t,a+t,b+t,x,y); 37 ul; ur; dl; 38 } 39 } 40 int main() 41 { 42 cin>>n>>x>>y; 43 dfs(1<<n,1,1,x,y); 44 return 0; 45 }