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的情况总能分解成42k-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 }

 

posted @ 2022-04-06 14:11  爱吃虾滑  阅读(136)  评论(0编辑  收藏  举报