切蛋糕java题,【算法•日更•第六期】头脑风暴:洛谷P1528 切蛋糕题解
▎(一个没有用处的)前言
为什么这次题解特意写明题号呢?因为我发现了这样的事情:
所以不要混了,想看P1714题解的同志们可以圆润的滚开了。
好了,不说没用的了,切入正题:
▎题目
题目及测评链接:戳这里
▎前置技能
▎解析
这道题看起来令人不知所措,不知道的东西太多了,到底如何分配,一看就是要用到搜索的题,但怕是连搜索也很难写了。
我们按照顺序一点一点的想:
首先,我们不知道如何分配,只能像无头苍蝇一样到处乱撞,所以我们可以先假设有多少人可以被满足,然后再实际用搜索检验一下这个假设是否可以成功,如果能行,那么增加这个假设的人数,继续试验;如果不行,那么就减少这个假设的人数,继续试验。
这就和原来不一样了,现在是有目标的,而且可以充分保证正确率。现在大致的思路就是这样的:
这就是我们的整体大思路,但是这样的方法时间复杂度显然是不可以的,我们需要一定的优化,其实优化是很简单的,只要有点生活常识就行:
①一块蛋糕一定能满足更多的嘴小的人,而不是更多嘴大的人。所以,贪心的想:如果将人按照嘴的大小排序,是不是更好呢?
②题目中明确规定不能将两块蛋糕拼起来,所以,如果一个人嘴大到连最大的蛋糕都无法满足,那就可以把他踢出去了,那么就不再考虑这个人了,因为无论如何都满足不了。所以依次(从大到小)把嘴大于最大的蛋糕的人全部排除掉,减少搜索判断次数,就可以起到优化的效果了。
③我们要先假设能满足的人数,那么该怎样假设呢?总得有个顺序吧,从小到大?从大到小?显然多一次假设就会多一次搜索,那么减少假设次数便是一个关键。于是我们便想到了二分,如果使用二分的话,就可以大大减少假设次数。
④剪枝优化1:每一次试探中蛋糕都会有所浪费,怎样判别是否浪费呢?显然,如果一块蛋糕分给一个人一部分后,剩下的连嘴最小的人都满足不了了,那么就一定浪费了。如果蛋糕总量减去浪费的蛋糕量(即这种方法剩下的蛋糕总量)比前n个人的总需求量还小,那么就说明无论如何都满足不了这n个人了,应该立即返回0,表示这种方案失败,换一种方案再继续搜索,这样就会少递归很多次。
⑤剪枝优化2:如果前一个人和这个人的嘴一样大,那么就可以优化判断前面的人是否可以被满足,减少for循环次数,由于这个人在第i个蛋糕之前的蛋糕都已经无法满足了(所以才会使用第i个蛋糕来满足),因为前一个人和这个人嘴一样大,所以前i个蛋糕也无法满足这个人了,因此,下一次循环可以特意从当前的i开始循环,而same_start也就是这样起到标记效果的。
▎Code speaks louder than words!
废话不多说了,详细的地方都已经写好了注释,直接上代码吧!
1 #include
2 #include
3 #define bug cout<
4 using namespacestd;5 int mouth[10000],cake[10000],c[10000],pre[10000],waste,all,n,m,l,r,mid,ans,maxn;//变量的意思(依次)6 //嘴的大小、蛋糕的大小、蛋糕大小副本、前缀和、浪费值、蛋糕总体积 、蛋糕个数、嘴的个数、二分左边界、右边界7 //二分的中点、答案、最大的蛋糕的体积
8 int dfs(int num,int same_start)//num表示剩下的要满足的人数,同时也巧妙的表示了人嘴的编号9 //same_start未剪枝时都可以当做1,而在进行剪枝时的用处详见上文
10 {11 if(num==0) return 1;//能够分配完所有的人,那么返回1
12 if(all-waste
13 for(int i=same_start;i<=n;i++)14 {15 if(c[i]>=mouth[num])16 {17 c[i]-=mouth[num];//如果能满足这个人,那么就让他吃掉,进行试探
18 if(c[i]
20 if(mouth[num]==mouth[num-1])//剪枝优化2,详见上文
21 {22 if(dfs(num-1,i)) return 1;23 }24 else if(dfs(num-1,1)) return 1;25 if(c[i]
26 c[i]+=mouth[num];//回溯
27 }28 }29 return 0;//如果是可以满足的,那么上面会返回的,否则就是不可以满足,返回0
30 }31 intmain()32 {33 cin>>n;34 for(int i=1;i<=n;i++)35 {36 cin>>cake[i];37 all+=cake[i];//记录蛋糕总量,用于剪枝
38 if(cake[i]>maxn) maxn=cake[i];//记录最大的蛋糕大小,后面有用
39 }40 cin>>m;41 for(int i=1;i<=m;i++)42 cin>>mouth[i];43 sort(mouth+1,mouth+m+1);//贪心:将每个人按嘴的大小排序
44 while(maxn
46 for(int i=1;i<=m;i++)47 pre[i]=pre[i-1]+mouth[i];//记录前缀和,用于剪枝
48 l=0;r=m;//规定好二分查找左右边界
49 while(l<=r)50 {51 waste=0;//浪费值初始为0
52 mid=(l+r)/2;53 for(int i=1;i<=n;i++) c[i]=cake[i];//如果在搜索中用cake数组的话,可能在没有回溯前就返回了,54 //那样cake值会变,影响下一轮搜索,所以赋值到c数组中,使用c数组代替,就像是常说的副本一样
55 if(dfs(mid,1))56 {57 ans=mid;//如果这个猜测能完成,那么就要记录下答案,不停覆盖,直到最后找到
58 l=mid+1;59 }60 else r=mid-1;//注意:这里千万不要写成r=mid,61 //因为当l=r时,mid=l=r,如果r=mid,那么就会陷入死循环,可以自己模拟一下,l会永远等于r62 //这种情况不可能r
64 }65 cout<
原文出处:https://www.cnblogs.com/TFLS-gzr/p/11157186.html
切蛋糕java题,【算法•日更•第六期】头脑风暴:洛谷P1528 切蛋糕题解相关推荐
- 【算法•日更•第七期】区间动态规划详解+一本通1570能量项链题解
▎前置基础 啥也不用说,不会动态规划绝对看不懂,请不会动态规划的同志们先戳这里了解基础动态规划. ▎什么是区间动态规划? 区间动态规划可以理解为用了分治的动态规划. 顾名思义,动态规划中涉及了区间,那 ...
- 【Leetcode单调队列】- 洛谷P1714切蛋糕
单调队列 解决该类问题的重点维护一个队列,从队首到队尾是递减的,队首是最大的.队尾是最小的. 队尾接受值,队首排出值. Java实现用双端队列,前面接收值,后面排出来值. 这类题目往往是跟滑动窗口一起 ...
- 洛谷刷题C语言:闰年判断、Apples、洛谷团队系统、肥胖问题、三位数排序
记录洛谷刷题QAQ 一.[深基3.例3]闰年判断 题目描述 输入一个年份,判断这一年是否是闰年,如果是输出 111,否则输出 000. 输入格式 输入一个正整数 nnn,表示年份. 输出格式 输出一行 ...
- 【算法•日更•第十九期】动态规划:RMQ问题
▎前言 首先先来说一下RMB是什么,当然是人民币啦. 今天我们要学的这个东西不一般,叫做RMQ问题,那么它和RMB有什么关系呢?待小编细细说来. ▎前置技能:动态规划 不会的同志请戳这里迅速了解动态规 ...
- HOJ 系统常用功能介绍 部署快速入门 c++ python java编程语言在线自动评测 信息奥赛一本通 USACO GESP 洛谷 蓝桥 CSP NOIP题库
技术支持微 makytony 服务器配置需求 腾讯云 2H4G 5M 60GB 轻量应用服务器 承载大约 200~400人使用,经过压力测试,评测并发速度可满足130人左右的在线比赛. 系统镜像选 ...
- 日更第8期-2015-3-23-如何科学地使用因特网-第三讲-为什么要用Git Bash?咱们用Github for Windows吧!(上)...
Hi!我又回来了!这次我保证,真的真的要开始日更了,绝对不会再断了!再断我就......我就再发次誓呗...... 不过说实话,最近确实有些忙,主要是大创的申请工作,弄得我焦头烂额的.不过我最近确实编 ...
- 闲来无事刷水题、简单博弈论专题、sg函数、洛谷
记 今天闲来无事,不想刷codeforces了,到洛谷提高组训练营找几道水题刷着玩玩(虽然自己早已过了打OI的年纪)- 简单博弈论专题 P1199 三国游戏 这么考虑,由于电脑总是不能让我搭配出当前能 ...
- 【算法•日更•第十二期】信息奥赛一本通1585:【例 1】Amount of Degrees题解
废话不多说,直接上题: 1585: [例 1]Amount of Degrees 时间限制: 1000 ms 内存限制: 524288 KB 提交数: 130 通过数: 68 ...
- 【算法•日更•第十五期】信息奥赛一本通1594:涂抹果酱题解
废话不多说,直接上题: 1594:涂抹果酱 时间限制: 1000 ms 内存限制: 524288 KB 提交数: 146 通过数: 46 [题目描述] Tyvj 两周年庆典要到 ...
- 【算法•日更•第三十期】区间动态规划:洛谷P4170 [CQOI2007]涂色题解
废话不多说,直接上题: P4170 [CQOI2007]涂色 题目描述 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符 ...
最新文章
- 关于Android 中 一个错误的解决办法 “Do not request Window.FEATURE_ACTION_BAR.....
- swing打地鼠游戏_【亲子早教】9月早教亲子游戏
- linux pam模块 cron,Linux-PAM 1.1.2 中文文档 - 6.32. pam_tally-登录计数器(统计)模块 | Docs4dev...
- zookeeper 分布式锁_关于redis分布式锁,zookeeper分布式锁原理的一些学习与思考
- Kryo序列化实现源码分析
- s7填表指令att_第五章 S7-200 指令系统.ppt
- 河北大学工商学院计算机分数线,河北大学工商学院录取分数线()
- python浮点数保留两位小数_(RPA)学习——Python 保存两位小数
- java将excel转换成txt_java将excel文件转换成txt格式文件
- oracle 数据库为nomount状态,oracle 数据库为nomount状态
- 2017.10.2 计算机算法分析----0-1背包问题
- FPGA-VGA驱动
- USB TYPE A B C 引脚定义
- html罗马字母怎么打,怎么打罗马数字二 罗马数字 在电脑上怎么打出来呢?
- 驱动备份及还原命令-手记
- python ttk_tkinter进阶版——ttk
- Excel的基本操作
- 腾讯云对象储存-图片上传-删除图片
- 前端开发公众号的调试
- x / k向上取整转换为向下取整
热门文章
- ptp输出内容包含什么_PTP 无线传输
- maven编译,执行测试用例报错 The forked VM terminated without saying properly goodbye. VM crash or System.exit c
- python中lines是什么类型_python中write和writelines有什么区别
- 【HDU 4609】3-idiots
- 2022-04- 聂卫平围棋道场-小汪小喵学围棋
- oracle用户 expire,Oracle用户expired
- studio无法重命名(can not rename root module)
- 产品需求文档(PRD)
- springboot项目快速搭建
- sqlserver创建函数后提示对象名无效