▎(一个没有用处的)前言

为什么这次题解特意写明题号呢?因为我发现了这样的事情:

所以不要混了,想看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 切蛋糕题解相关推荐

  1. 【算法•日更•第七期】区间动态规划详解+一本通1570能量项链题解

    ▎前置基础 啥也不用说,不会动态规划绝对看不懂,请不会动态规划的同志们先戳这里了解基础动态规划. ▎什么是区间动态规划? 区间动态规划可以理解为用了分治的动态规划. 顾名思义,动态规划中涉及了区间,那 ...

  2. 【Leetcode单调队列】- 洛谷P1714切蛋糕

    单调队列 解决该类问题的重点维护一个队列,从队首到队尾是递减的,队首是最大的.队尾是最小的. 队尾接受值,队首排出值. Java实现用双端队列,前面接收值,后面排出来值. 这类题目往往是跟滑动窗口一起 ...

  3. 洛谷刷题C语言:闰年判断、Apples、洛谷团队系统、肥胖问题、三位数排序

    记录洛谷刷题QAQ 一.[深基3.例3]闰年判断 题目描述 输入一个年份,判断这一年是否是闰年,如果是输出 111,否则输出 000. 输入格式 输入一个正整数 nnn,表示年份. 输出格式 输出一行 ...

  4. 【算法•日更•第十九期】动态规划:RMQ问题

    ▎前言 首先先来说一下RMB是什么,当然是人民币啦. 今天我们要学的这个东西不一般,叫做RMQ问题,那么它和RMB有什么关系呢?待小编细细说来. ▎前置技能:动态规划 不会的同志请戳这里迅速了解动态规 ...

  5. HOJ 系统常用功能介绍 部署快速入门 c++ python java编程语言在线自动评测 信息奥赛一本通 USACO GESP 洛谷 蓝桥 CSP NOIP题库

    技术支持微 makytony 服务器配置需求 腾讯云 2H4G 5M 60GB 轻量应用服务器  承载大约 200~400人使用,经过压力测试,评测并发速度可满足130人左右的在线比赛. 系统镜像选 ...

  6. 日更第8期-2015-3-23-如何科学地使用因特网-第三讲-为什么要用Git Bash?咱们用Github for Windows吧!(上)...

    Hi!我又回来了!这次我保证,真的真的要开始日更了,绝对不会再断了!再断我就......我就再发次誓呗...... 不过说实话,最近确实有些忙,主要是大创的申请工作,弄得我焦头烂额的.不过我最近确实编 ...

  7. 闲来无事刷水题、简单博弈论专题、sg函数、洛谷

    记 今天闲来无事,不想刷codeforces了,到洛谷提高组训练营找几道水题刷着玩玩(虽然自己早已过了打OI的年纪)- 简单博弈论专题 P1199 三国游戏 这么考虑,由于电脑总是不能让我搭配出当前能 ...

  8. 【算法•日更•第十二期】信息奥赛一本通1585:【例 1】Amount of Degrees题解

    废话不多说,直接上题: 1585: [例 1]Amount of Degrees 时间限制: 1000 ms         内存限制: 524288 KB 提交数: 130     通过数: 68 ...

  9. 【算法•日更•第十五期】信息奥赛一本通1594:涂抹果酱题解

    废话不多说,直接上题: 1594:涂抹果酱 时间限制: 1000 ms         内存限制: 524288 KB 提交数: 146     通过数: 46 [题目描述] Tyvj 两周年庆典要到 ...

  10. 【算法•日更•第三十期】区间动态规划:洛谷P4170 [CQOI2007]涂色题解

    废话不多说,直接上题:  P4170 [CQOI2007]涂色 题目描述 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符 ...

最新文章

  1. 关于Android 中 一个错误的解决办法 “Do not request Window.FEATURE_ACTION_BAR.....
  2. swing打地鼠游戏_【亲子早教】9月早教亲子游戏
  3. linux pam模块 cron,Linux-PAM 1.1.2 中文文档 - 6.32. pam_tally-登录计数器(统计)模块 | Docs4dev...
  4. zookeeper 分布式锁_关于redis分布式锁,zookeeper分布式锁原理的一些学习与思考
  5. Kryo序列化实现源码分析
  6. s7填表指令att_第五章 S7-200 指令系统.ppt
  7. 河北大学工商学院计算机分数线,河北大学工商学院录取分数线()
  8. python浮点数保留两位小数_(RPA)学习——Python 保存两位小数
  9. java将excel转换成txt_java将excel文件转换成txt格式文件
  10. oracle 数据库为nomount状态,oracle 数据库为nomount状态
  11. 2017.10.2 计算机算法分析----0-1背包问题
  12. FPGA-VGA驱动
  13. USB TYPE A B C 引脚定义
  14. html罗马字母怎么打,怎么打罗马数字二 罗马数字 在电脑上怎么打出来呢?
  15. 驱动备份及还原命令-手记
  16. python ttk_tkinter进阶版——ttk
  17. Excel的基本操作
  18. 腾讯云对象储存-图片上传-删除图片
  19. 前端开发公众号的调试
  20. x / k向上取整转换为向下取整

热门文章

  1. ptp输出内容包含什么_PTP 无线传输
  2. maven编译,执行测试用例报错 The forked VM terminated without saying properly goodbye. VM crash or System.exit c
  3. python中lines是什么类型_python中write和writelines有什么区别
  4. 【HDU 4609】3-idiots
  5. 2022-04- 聂卫平围棋道场-小汪小喵学围棋
  6. oracle用户 expire,Oracle用户expired
  7. studio无法重命名(can not rename root module)
  8. 产品需求文档(PRD)
  9. springboot项目快速搭建
  10. sqlserver创建函数后提示对象名无效