【YbtOJ】生日蛋糕
【YbtOJ】生日蛋糕
好家伙这在洛谷是道蓝题
题面
题目描述
7 月 17 日是 Mr.W 的生日,ACM-THU 为此要制作一个体积为
的 层生日蛋糕,每层都是一个圆柱体。 设从下往上数第
层蛋糕是半径为 ,高度为 的圆柱。当 时,要求 且 。 由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积
最小。 请编程对给出的
和 ,找出蛋糕的制作方案(适当的 和 的值),使 最小。 (除
外,以上所有数据皆为正整数) 输入格式
第一行为一个整数
,表示待制作的蛋糕的体积为 。 第二行为
,表示蛋糕的层数为 。 输出格式
输出一个整数
,若无解,输出 。 样例输入
100 2 样例输出
68
分析
-
蛋糕的表面积为各层侧面积之和加上底层的上表面面积
-
基本的思路其实很简单
从下向上搜索每一层的高度
与半径 并记录目前的总表面积 、还需要的体积 以及当前层数- 如果已经到达了最顶层,检查
是否为 ,即体积是否等于- 若体积恰巧等于
则找到一种解,比较 与目前最小表面积 - 若体积不相等,则这种方法不符合规则应舍弃
- 若体积恰巧等于
- 枚举
和 ,判断侧面积 、 目前体积 是否合法,不合法就跳过
- 如果已经到达了最顶层,检查
-
所有式子里面都有
可以将其提出来,在运算过程中忽略掉
剪枝
-
先给出我最开始写出来的、显而易见的剪枝
- 若目前的总表面积已经超过了
,很显然最后的结果一定会超过目前的最小值 - 如果加上该层蛋糕的体积后总体积超过所求体积,最后答案一定非法
- 若目前的总表面积已经超过了
-
然后是书中给出的剪枝方法(
记当前表面积为
,当前体积 ,当前处于 层(最上层为第 层)-
上下界剪枝
根据
可得-
由于
最小为 ,则 的最大值为但考虑到
不能超过上一层的因此
的最大值为由于每一层的
都需要小于上一层的 ,可知 的最小值就是因此,
的取值范围是 -
,由于是先枚举 再枚举 ,因此这个 可以留下来其余部分同
因此
的取值范围为
-
-
优化搜索顺序
在上面确定的范围中,采用倒序枚举
因为该层的
和 越大,留给接下来的蛋糕的 和 的范围就越大 -
可行性剪枝
可以预处理出从上往下前
层的最小体积和侧面积,显然,当第 ~ 层的半径分别取 ,高度也分别取 时,有最小体积和侧面积如果当前体积
加上 层的最小体积大于 ,可以剪枝 -
最优性剪枝一
如果当前表面积
加上 层的最小侧面积大于已经搜到的答案,剪枝 -
最优性剪枝二
(下列描述忽略
)利用
与 数组, 层的体积可表示为 层的侧面积可表示为因为
所以当
(即目前的 加上上面的所有层侧面积最小值仍然大于已经搜到的答案)时,可以剪枝
-
代码
#include <bits/stdc++.h> using namespace std; int n, m; int minS = 1e9; inline int CS(int r, int h) { return 2 * r * h; } inline int CV(int r, int h) { return r * r * h; } void dfs(int N, int R, int H, int cnt, int sc) { if (sc > minS) return; if (cnt == m + 1) { if (N != 0) return; minS = min(minS, sc); return; } int k = m - cnt + 1; if (k * R * R * H < N) return; if (k * 2 + sc > minS) return; if (cnt == 1) { for (int r = R; r >= m; r--) { for (int h = m; h <= H; h++) { int cs = CS(r, h); int cv = CV(r, h); if (N - cv < 0) continue; if (r * r * h > n) continue; dfs(N - cv, r, h, cnt + 1, sc + cs + r * r); } } } else for (int r = R - 1; r >= m - cnt + 1; r--) { for (int h = m - cnt + 1; h < H; h++) { int cs = CS(r, h); int cv = CV(r, h); if (N - cv < 0) continue; if (r * r * h > n) continue; dfs(N - cv, r, h, cnt + 1, sc + cs); } } } int main() { scanf("%d%d", &n, &m); dfs(n, 50, 50, 1, 0); printf("%d", minS); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】