浅谈分治 —— 洛谷P1228 地毯填补问题 题解
如果想看原题网址的话请点击这里:地毯填补问题
原题:
题目描述
相传在一个古老的阿拉伯国家里,有一座宫殿。宫殿里有个四四方方的格子迷宫,国王选择驸马的方法非常特殊,也非常简单:公主就站在其中一个方格子上,只要谁能用地毯将除公主站立的地方外的所有地方盖上,美丽漂亮聪慧的公主就是他的人了。公主这一个方格不能用地毯盖住,毯子的形状有所规定,只能有四种选择(如图):
(此处图误见后处的图)
并且每一方格只能用一层地毯,迷宫的大小为 ^k * ^k的方形。当然,也不能让公主无限制的在那儿等,对吧?由于你使用的是计算机,所以实现时间为1s。 输入格式
输入文件共 行。 第一行:kk,即给定被填补迷宫的大小为 ^k * ^k
第二行:x,yx,y,即给出公主所在方格的坐标(xx 为行坐标,yy 为列坐标),xx 和 yy 之间有一个空格隔开。 输出格式
将迷宫填补完整的方案:每一补(行)为x\ y\ cx y c(x,yx,y 为毯子拐角的行坐标和列坐标, cc 为使用毯子的形状,具体见上面的图 ,毯子形状分别用 ,,,,,, 表示,x,y,cx,y,c 之间用一个空格隔开)。 输入输出样例
输入 # 复制 输出 # 复制 说明/提示
事实上感觉四个的形状分别是这样(仅供参考,如果有问题联系 icy)
图见原题
spj 报错: cc 越界
x,yx,y 越界
mp[x][y]mp[x][y] 已被占用
mp[x][y]mp[x][y] 从未被使用
首先在分析该题之前ROS先解释一下这里的行坐标和列坐标:
此处的行坐标表示的是第几行,而列坐标表示的是第几列;此处的坐标定义与我们平常使用的平面直角坐标系中的坐标前后表示意义正好相反,所以需要解释一下(一开始ROS就是因为没有看懂这点所以写出了一些前后矛盾的代码)
好的行坐标和列坐标的意义解释完了,现在开始分析题目:
先来解析题目构建算法,那么这道题我们看到被洛谷贴上了“分治”的标签所以一定要用分治的思想。
先来解析题目构建算法,我们一开始来看这道题就想一种最暴力的算法:可不可以尝试给每个位置都尝试能否铺上4种地毯中的一种然后用一个vis数组来储存是否被访问过,如果其中出现了一块四种地毯都铺不了的位置时我们则回溯到上一状态呢?然而经过大概分析可以得知这一算法是肯定不行的,就单单给每个位置都访问一遍并且假设从一开始到最后永不回溯且每次地毯都恰好正确就需要2^2k次访问,但是这是不可能的,所以这种暴力dfs的做法就算是最好的情况下才会过但这种情况出现的可能性为0(除非有人无聊到专门做一个为了给这种做法的人得分的数据……)。所以这种暴力dfs的算法直接pass
那么我们在分析之后将问题简化:如果我们面对的问题是对于一个有四个格的正方形方块,我们知道公主站在其中一个格子上那么我们如何铺地毯呢?这显然是一个很简单的问题:把地毯铺在剩下三个剩余空间的地板上就可以了。(①)
我们的算法就是从这种思想(①)入手的。
没错这种想法看似很简单但是我们却可以从这种简单的思想中寻找我们需要的分治算法思想。
那么如果我们我们想象公主站在一个有2^k * 2^k个地板的方形上,那么我们可以将这个大的方形想象成4个大块,而公主则想象站在四个大块的其中一个上,那么我们的问题就变成了(①)中的问题,只需要把地毯铺在剩余3块大块上就可以了。那么我们就做完了。(②)
那么我们该把这个我们假想的这三块地毯铺在哪里呢?(③)
就铺在这一个方形的中间4个小地板的3个大块所对应的小地板上。(④)
然后我们对于那个有公主站着的大块我们再“把视角拉近”,把这一个大块分成4个小块。然后进行(②)(③)(④)的操作。
这就是分治的思想,即将问题一步步分解成小问题从而对分解出来的小问题求解最终就求出了想要的整体解。
其实对于(①)我们还可以有另一种解释,那就是我们可以将这四个大块的状态(公主是否站在上面)压缩到最中间的4个小方块上,所以我们就可以理所当然的将地毯铺在最中间的4的块中的3个上了。
那么下面是代码实现:
(说实话ROS算法思想其实早就懂了但是代码一直不会实现今天才把代码写完)
#include<bits/stdc++.h>
using namespace std;
int k,x,y;
void dfs(int a,int b,int c,int e,int f);
int ksm(int x,int y);
int main(){
scanf("%d%d%d",&k,&x,&y);
dfs(x,y,k,,);
return ;
}
int ksm(int x,int y){
if(x==||x==) return x;
if(y==) return ;
if(y==) return x;
int tmp=ksm(x,y/);
if(y&){
return tmp*tmp*x;
}
return tmp*tmp;
}
void dfs(int a,int b,int c,int e,int f){
if(c==) return ;
int tmp=ksm(,c-);
if(a<=e+tmp-){
if(b<=f+tmp-){
printf("%d %d 1\n",e+tmp,f+tmp);
dfs(e+tmp,f+tmp,c-,e+tmp,f+tmp);
dfs(e+tmp,f+tmp-,c-,e+tmp,f);
dfs(e+tmp-,f+tmp,c-,e,f+tmp);
if(c>=) dfs(a,b,c-,e,f);
return ;
}
else{
printf("%d %d 2\n",e+tmp,f+tmp-);
dfs(e+tmp,f+tmp-,c-,e+tmp,f);
dfs(e+tmp,f+tmp,c-,e+tmp,f+tmp);
dfs(e+tmp-,f+tmp-,c-,e,f);
if(c>=) dfs(a,b,c-,e,f+tmp);
return ;
}
}
if(a>e+tmp-){
if(b>f+tmp-){
printf("%d %d 4\n",e+tmp-,f+tmp-);
dfs(e+tmp-,f+tmp-,c-,e,f);
dfs(e+tmp-,f+tmp,c-,e,f+tmp);
dfs(e+tmp,f+tmp-,c-,e+tmp,f);
if(c>=) dfs(a,b,c-,e+tmp,f+tmp);
return ;
}
else{
printf("%d %d 3\n",e+tmp-,f+tmp);
dfs(e+tmp-,f+tmp,c-,e,f+tmp);
dfs(e+tmp-,f+tmp-,c-,e,f);
dfs(e+tmp,f+tmp,c-,e+tmp,f+tmp);
if(c>=) dfs(a,b,c-,e+tmp,f);
return ;
}
}
return ;
}
由于ROS原来正是因为有一些困惑再加上ROS及其讨厌看题解(ROS认为这会影响到人的自主思维)而导致不会代码实现所以ROS把我当时的困惑说出来并进行解答:
1.
Q:如何实现我在搜索哪一个“大块”?
A:对于这一问题,ROS一开始真的不知道怎么表示。但后来ROS发现有于我们进行分治的思想所以我们可以知道我们这一次所进行搜索的正方形块边长是多少,所以我们可以通过一个块的坐标和正方形边长就可以得到我们在搜索的这个大块的具体坐标范围了。
2.
Q:有没有可能会出现最终有的地板没有相应的可以铺的地毯的情况?
A:这是不可能的。因为我们已经得知方形的边长为2^k所以一步步分下去(每一次分成4个等大的小块)一定是可以恰好有唯一情况分完的。
最后总结:分治就是把一个整体的大问题分成一个个可以解决的小问题然后解决小问题的过程。这种思想和递归类似,而与递归不同的是递归通常还是长时间消耗的代名词,而分治则通常不会消耗过长时间(以为没有调用自身的过程而把问题分解了)
浅谈分治 —— 洛谷P1228 地毯填补问题 题解的更多相关文章
- [洛谷P1228]地毯填补问题 题解(分治)
Description 相传在一个古老的阿拉伯国家里,有一座宫殿.宫殿里有个四四方方的格子迷宫,国王选择驸马的方法非常特殊,也非常简单:公主就站在其中一个方格子上,只要谁能用地毯将除公主站立的地方外的 ...
- 洛谷P1228 地毯填补问题
P1228 地毯填补问题 题目描述 相传在一个古老的阿拉伯国家里,有一座宫殿.宫殿里有个四四方方的格子迷宫,国王选择驸马的方法非常特殊,也非常简单:公主就站在其中一个方格子上,只要谁能用地毯将除公主站 ...
- 浅谈SPFA——洛谷P1576 最小花费 题解
想找原题请点击这里:传送门 原题: 题目描述 在n个人中,某些人的银行账号之间可以互相转账.这些人之间转账的手续费各不相同.给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少 ...
- P1228 地毯填补问题(分治)
P1228 地毯填补问题(分治) 题目描述 相传在一个古老的阿拉伯国家里,有一座宫殿.宫殿里有个四四方方的格子迷宫,国王选择驸马的方法非常特殊,也非常简单:公主就站在其中一个方格子上,只要谁能用地毯将 ...
- 洛谷P1783 海滩防御 分析+题解代码
洛谷P1783 海滩防御 分析+题解代码 题目描述: WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和 ...
- 洛谷P4047 [JSOI2010]部落划分题解
洛谷P4047 [JSOI2010]部落划分题解 题目描述 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落 ...
- 洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈)
洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1311990 原题地址:洛谷P1155 双栈排序 ...
- 洛谷10月月赛II题解
[咻咻咻] (https://www.luogu.org/contestnew/show/11616) 令人窒息的洛谷月赛,即将参加NOIp的我竟然只会一道题(也可以说一道也不会),最终145的我只能 ...
- [NOIP提高&洛谷P1024]一元三次方程求解 题解(二分答案)
[NOIP提高&洛谷P1024]一元三次方程求解 Description 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约 ...
随机推荐
- execute、executeUpdate、executeQuery的区别
链接:https://blog.csdn.net/u012501054/article/details/80323176 链接:https://blog.csdn.net/CNAHYZ/article ...
- static静态不是很静
在类中定义变量时,不会开辟存储空间,只有类定义一个对象时才会开辟类中成员变量的内存空间,且建立一个对象开辟一次,大小与类中的成员变量及函数有关.而static在静态区开辟内存空间,不占用内存空间. 1 ...
- join方法,wait()和sleep()
join方法解释:方法x.join()的作用是使所属线程x 正常执行run()中的方法,而使得调用x.join()的线程处于无限期阻塞状态,等待x线程销毁后再继续执行线程z后面的代码. 1.方法joi ...
- JavaScript函数、对象和数组
一.JavaScript函数 1.定义函数:函数的通用语法如下 function function_name([parameter [, ...]]) { statements; } 由关键字func ...
- [一本通学习笔记] AC自动机
AC自动机可以看作是在Trie树上建立了fail指针,在这里可以看作fail链.如果u的fail链指向v,那么v的对应串一定是u对应串在所给定字符串集合的后缀集合中的最长的后缀. 我们考虑一下如何实现 ...
- python面试的100题(2)
def print_directory_contents(sPath): """ 这个函数接收文件夹的名称作为输入参数 返回该文件夹中文件的路径 以及其包含文件夹中文件的 ...
- 九、c++容器
9.1 简介 容器库是类模板与算法的汇集,允许程序员简单地访问常见数据结构,例如队列.链表和栈. 有三类容器--顺序容器.关联容器和无序关联容器--每种都被设计为支持不同组的操作. 顺序容器:顺序容器 ...
- 并发之ATOMIC原子操作--CAS乐观锁原理(二)
1.乐观锁介绍 程序完成并发操作时,访问数据时每次不加锁,假设没有冲突去完成某项操作,如果因为冲突失败就重试,直到成功为止.就是当去做某个修改或其他操作的时候它认为不会有其他线程来做同样的操作(竞争) ...
- nginx的学习
什么是反向代理? 参考这个帖子的‘刘志军’的回答 https://www.zhihu.com/question/24723688 nginx的配置 http://baijiahao.baidu.com ...
- 配置SSH使用密钥认证:实现免输入密码登陆
一.实际工作生产场景分析 张三是某公司员工,由于业务上的需求,需要经常使用SSH工具登陆服务器A的root账户进行操作,为避免重复进行密码验证身份.现采用张山的公钥发送给服务器A,免输入密码登陆到服务 ...