【题解】洛谷P731[NOI1999] 生日蛋糕+数据加强版
前言:阅读理解+剪枝+头脑风暴
Designed By FrankWkd 遵循GNU GPL2.0开源协议。
该代码可以通过T148457 生日蛋糕加强版 和 P1731 [NOI1999] 生日蛋糕.
P1731 [NOI1999] 生日蛋糕
题目背景
题目描述
7 月 17 日是 Mr.W 的生日,ACM-THU 为此要制作一个体积为 \(N\pi\) 的 \(M\) 层生日蛋糕,每层都是一个圆柱体。
设从下往上数第 \(i\)(\(1 \leq i \leq M\))层蛋糕是半径为 \(R_i\),高度为 \(H_i\) 的圆柱。当 \(i \lt M\) 时,要求 \(R_i \gt R_{i+1}\) 且 \(H_i \gt H_{i+1}\)。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积 \(Q\) 最小。
请编程对给出的 \(N\) 和 \(M\),找出蛋糕的制作方案(适当的 \(R_i\) 和 \(H_i\) 的值),使 \(S=\dfrac{Q}{\pi}\) 最小。
(除 \(Q\) 外,以上所有数据皆为正整数)
输入格式
第一行为一个整数 \(N\)(\(N \leq 2 \times 10^4\)),表示待制作的蛋糕的体积为 \(N\pi\)。
第二行为 \(M\)(\(M \leq 15\)),表示蛋糕的层数为 \(M\)。
输出格式
输出一个整数 \(S\),若无解,输出 \(0\)。
输入输出样例 #1
输入 #1
100
2
输出 #1
68
思路
我们先来解决 \(S=\dfrac{Q}{\pi}\),那么众所周知,\(Q=\) 所有圆环(柱)的上表面面积 \(+\) 侧面面积 ,那么我们看下图:
图源侵删
该图中的黑色部分就是我们要计算的圆环(柱)的上表面面积,我们将整合图形从上到下拍扁,就得到了一个圆柱,这个圆柱的上表面面积(也就是一个圆)就是图中黑色部分的面积。(我们设 \(R_i\) 和 \(H_i\) 为第 \(i\) 层的半径和体积)
那么第 \(1\sim i\) 层的表面积
\]
\]
所以说 \(S\) 就是去掉 \(\pi\) 后的图形表面积。也就是 \(\sum2R_{i}H_{i}+R_{M}^{2}\)
本题就转化成了求该图形的表面积除 \(\pi\) 后的值(是整数)。
剪枝
我们设最上层的编号为 \(1\),当前 \(DFS\) 的层数为 \(u\) ,总层数为 \(m\),如下图(\(u+1\) 不一定等于 \(m\)):
优化搜索顺序
- 我们从下向上搜索,因为下层面积大,分支少。
- 每一层的 \(R\) 和\(H\) 从大到小枚举,因为开始的时候枚举大的数据分支就会变小,搜到数据时累计的循环次数就会比先暴搜小分支的时候小。
上下界剪枝 (接下来所有公式和等式均忽略 \(\pi\))
现在我们要确定 \(R_u\) 和 \(H_u\) 的范围。
- 最小值:因为当前再第 \(u\) 层,第 \(1\) 层的最小值为 \(1\),第 \(2\) 层的最小值为 \(2\),以此类推,第 \(u\) 层的 \(R_u\) 和 \(H_u\) 的最小值为 \(u\)。
- 最大值:
- 我们当前已经确定了第 \(m\sim u+1\) 层的 \(R\) 和 \(H\),我们设第 \(m\sim u+1\) 层的体积和为 \(v\) ,那第 \(1\sim u\) 层的体积和为 \(n-v\) ,那当前这一层的体积肯定小于等于还未计算所有体积,即 \(R_u^2H_u\le n-v\)。既然我们要计算 \(R_u\) 的最大值,那么我们不妨将 \(H_u\) 设为 \(1\) ,即 \(R_u^2\le n-v\),\(R_u\le \sqrt{n-v}\).
- 根据题目内容,\(R_i >R_{i+1}\) ,因为我们是反向遍历的,所以就是 \(R_u < R_{u+1}\) 。\(H_u\) 同理.
\]
\]
可行性剪枝
我们预处理出 \(1\sim m\) 层的最小体积 \(minv[i]\) 表示第 \(1\sim i\) 层的最小体积,如果当前已经算出来的 \(u+1\sim m\) 层的体积 \(v\) 加上 \(minv[u]\) 大于总体积 \(n\) 的话,就直接 \(return\) 。
最优化剪枝
我们预处理出 \(1\sim m\) 层的最小表面积 \(mins[i]\) 表示第 \(1\sim i\) 层的最小表面积,如果当前已经算出来的 \(u+1\sim m\) 层的表面积 \(s\) 加上 \(mins[u]\) 大于当前已经搜到的合法答案的最小资 \(ans\) 的话,就直接 \(return\) 。
图源侵删
最优化剪枝 Plus (遇事不明请看上图)
\(1\sim u\) 层的最小侧面积和还可以用剩余体积 \(n-v\) 来估价。
\(1\sim u\) 层的体积和为: \(\sum_{i=1}^{{u}}{R}_{{i}}^{2}*{H}_{{i}}=n-v\),
\(1\sim u\) 层的侧面积和 \(2\sum _{{i= 1}}^{{u} }R_{{i} }* H_{{i} }\)
提公因式 \(R_u\) 得:
\]
因为我们是使用 \(\sum_{i=1}^{u}\) 遍历 \(1\sim u\) 中的所有数,所以肯定保证 \(i \le u\).这里我也理解了好长时间,\(\sum_{i=1}^{u}\) 等同于:for(int i = 1;i <= u;i++)
,所以在 \(for\) 里面执行的时候 \(i\) 一定 \(\le u\). 我们把原式中的的一个 \(R_u\) 换成 \(R_i\),这个式子肯定是小于等于没换的式子的。即:
\]
还记得 \(1\sim u\) 层的体积和吗?\(\sum_{i=1}^{{u}}{R}_{{i}}^{2}*{H}_{{i}}=n-v\)
将 \(\frac 2{{R_{u}} }\sum _{{i= 1}}^{{u} }R_{{i} }^{2}* H_{{i} }\) 中的 \(\sum_{i=1}^{{u}}{R}_{{i}}^{2}*{H}_{{i}}\) 替换为 \(n-v\) ,就变成了 \(\frac{2(n-v)}{R_{u}}\)。
这时你会发现 \(R_u\) 是未知的! 我们将 \(R_u\) 替换为 \(R_{u+1}\) 这时候,\(\frac{2(n-v)}{R_{u+1}}<\frac{2(n-v)}{R_{u}}\)
所以,如果 \(s+\frac{2({n}-{v})}{{R}_{u+1}}>ans\),既然小的那个式子 \(+s\) 都比当前的最优解差,那么 \(s+\frac{2(n-v)}{R_{u}}\) 一定大于当前的最优解 \(ans\),那么剪枝。
该估价不等式类似 \(A^*\)算法中的估价函数思想。(\(\frac{2(n-v)}{R_{u+1}}+s\) 类似于估价函数)
数据梳理
体积: \(n=\sum_{i=1}^mR_i^2H_i\)
面积:\(S=\sum2R_iH_i+R_M^2\)
剪枝:
- 1.优化搜索顺序
- 2.上下界剪枝
- \[R\in [u,min(R_{u+1}-1,\sqrt{n-v})]
\] - \[H\in [u,min(H_{u+1}-1,\frac{n-v}{R_{u}\times R_{u}})]
\]
- 3.可行性剪枝(体积和越界)
- \[v+minv[u] > n
\]
- 4.最优性剪枝(面积和更差)
- \[s+mins[u]>ans
\]
- 最优性剪枝(面积和更差)
- \[s+\frac{2(n-v)}{R_{u+1}} > ans
\]
为什么要保留两个面积和更差的剪枝?
【Powered By Doubao】
第4、5个剪枝虽都围绕表面积优化,但二者存在本质差异与互补性,具体原因如下:
1. 原理不同,覆盖不同逻辑分支
- 第4个剪枝:基于预处理的固定值
mins[u]
(前u
层最小侧面积和,每层取半径、高度为层号时的侧面积累加)。它是一种“静态通用下限”,只要当前表面积s + mins[u] > ans
,就说明即使剩余层取理论最小侧面积,总表面积仍超最优解,直接剪枝。 - 第5个剪枝:通过剩余体积
n - v
动态推导侧面积下限,结合半径关系(如R_{u+1}
)。它是“动态实时下限”,利用剩余体积的分配逻辑,推导出侧面积必然超标的情况,剪枝与剩余体积强相关的无效分支。
2. 场景互补,提升剪枝全面性
- 第4个剪枝:处理“仅侧面积部分就已超最优解”的通用场景,不依赖剩余体积的具体数值,通过预处理数组快速判断。
- 第5个剪枝:处理“因剩余体积分配导致侧面积超标”的特殊场景,利用体积与半径的数学关系,覆盖第4个剪枝未涉及的逻辑。
3. 效率互补,减少无效计算
- 单独使用第4个剪枝,无法利用剩余体积的动态信息,可能遗漏与体积相关的无效分支;单独使用第5个剪枝,缺少对通用最小侧面积的快速判断。
- 两者结合,从“固定预处理下限”和“动态体积推导下限”两个维度,更全面地过滤无效搜索路径,大幅减少DFS的计算量,提升算法效率。
代码
#include <bits/stdc++.h>
using namespace std;
const int Inf = 1e9;
int minv[30],mins[20],n,m;
int ans = Inf;
void dfs(int u,int r,int h,int v,int s){
if(u == 0){
if(s < ans and v == n) ans = s;
return ;
}
if(v+minv[u] > n) return;
if(s+mins[u]>=ans) return;
if(s+2*(n-v)/r >= ans) return;
for(int i = min(r-1,(int)sqrt(n-v));i >= u;i--){
for(int j = min(h-1,(n-v)/(i*i));j >= u;j--){
dfs(u-1,i,j,v+i*i*j,s+2*i*j+(u==m?i*i:0));
}
}
}
int main(){
cin>>n>>m;
for(int i = 1;i <= m;i++){
mins[i] = mins[i-1]+2*i*i;
minv[i] = minv[i-1]+i*i*i;
}
dfs(m,Inf,Inf,0,0);//从下向上遍历
if(ans == Inf) puts("0");
else cout<<ans<<endl;
}
注释版本:
【题解】洛谷P731[NOI1999] 生日蛋糕+数据加强版的更多相关文章
- 洛谷P1120 小木棍 [数据加强版](搜索)
洛谷P1120 小木棍 [数据加强版] 搜索+剪枝 [剪枝操作]:若某组拼接不成立,且此时 已拼接的长度为0 或 当前已拼接的长度与刚才枚举的长度之和为最终枚举的答案时,则可直接跳出循环.因为此时继续 ...
- 【题解】洛谷P1731 [NOI1999] 生日蛋糕(搜索+剪枝)
洛谷P1731:https://www.luogu.org/problemnew/show/P1731 思路 三重剪枝 当前表面积+下一层表面积如果超过最优值就退出 当前体积+下一层体积如果超过总体积 ...
- 洛谷 P1731 [NOI1999]生日蛋糕
P1731 [NOI1999]生日蛋糕 题目背景 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层 生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1<=i<=M ...
- 洛谷——P1731 [NOI1999]生日蛋糕
P1731 [NOI1999]生日蛋糕 搜索+剪枝 常见的剪枝: 若当前状态+后面所要搜索的最差的状态$>$或是$<$最后的状态,就返回 预处理最差的状态 #include<iost ...
- C++ 洛谷 P1731 [NOI1999]生日蛋糕
P1731 [NOI1999]生日蛋糕 一本通上也有. 这TM是一道极其简单的深搜剪枝(DP当然可以的了,这里我只讲深搜). 首先圆柱公式:(有点数学基础都知道) V=πR2H S侧=π2RH S底= ...
- 洛谷 P1731 [NOI1999]生日蛋糕 && POJ 1190 生日蛋糕
题目传送门(洛谷) OR 题目传送门(POJ) 解题思路: 一道搜索题,暴力思路比较容易想出来,但是这道题不剪枝肯定会TLE.所以这道题难点在于如何剪枝. 1.如果当前状态答案已经比我们以前某个状态 ...
- 洛谷 P1731 [NOI1999]生日蛋糕 题解
每日一题 day53 打卡 Analysis 观察一个蛋糕的俯视图,上表面的面积其实就是最下面那一层的底面积,所以在第一次搜索的时候加入这个底面积,之后就只用考虑侧面积就好啦. 就是每次枚举r和h,如 ...
- POJ1190 洛谷P1731 NOI1999 生日蛋糕
生日蛋糕(蛋糕是谁?) Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 20272 Accepted: 7219 Desc ...
- [洛谷P1731][NOI1999]生日蛋糕(dfs)(剪枝)
典型的深搜+剪枝策略 我们采用可行性剪枝.上下界剪枝.优化搜索顺序剪枝.最优性剪枝的方面来帮助我们进行剪枝. 也许有人还不知道剪枝,那我就弱弱地为大家补习一下吧qwq: .优化搜索顺序: 在一些搜索问 ...
- 洛谷P1731 [NOI1999]生日蛋糕(爆搜)
题目背景 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层 生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1<=i<=M)层蛋糕是半径为Ri, 高度为Hi的圆柱 ...
随机推荐
- java中的ArrayBlockingQueue
ArrayBlockingQueue ArrayBlockingQueue 是 Java 并发包 (java.util.concurrent) 中的一个线程安全的阻塞队列实现. 它基于数组实现,容量固 ...
- Protobuf生成文件报错
Mac下protobuf生成文件报错问题解决办法,windows下就不会这么麻烦了,如果linux下出现类似报错信息按照下面的解决逻辑依然适用. 1.由--go_out引发的报错 1.报错信息: us ...
- Clickhouse常见异常
一.异常 1)DB::Exception: Nested type Array(String) cannot be inside Nullable type (version 20.4.6.53 (o ...
- Math.atan2求角度解析
我们求角度的时候, 第一反应应该是Math.tan(x/y)就得到角度了 但是这样求的是和y轴的夹角,如果以y轴正方向为0度,顺时针为正,则第三象限和第一象限的tan值一致,需要判断x,y和0的关系, ...
- macbookpro m3本地部署DeepSeek模型
macbookpro m3有着十分强大的性能.在deepseek如火如荼的当下,可以尝试在本地部署并使用.还可以将自己的文档作为语料喂给deepseek,使其能成为自己专属的AI助手. 本文介绍使用o ...
- 异地组网工具 Radmin_LAN:将远程计算机连接到单一本地网络
Radmin LAN是一款使用简单的免费软件产品,用于创建虚拟本地网络.该程序允许用户安全地连接位于防火墙后的计算机.为流量提供一个安全通道.可靠的端到端加密(256位AES)确保您的连接安全. Ra ...
- SIT、UAT以及PROD环境的区别
题记部分 一.SIT环境 SIT(System Integration Testing)环境主要用于系统集成测试,旨在验证系统中不通模块之间的集成和交互是否正常工作.这个环境通常用于开发团队内部进 ...
- Linux - 配置IP&主机名的快捷操作
nmtui 执行以下命令可以进入一个可视化界面,进行IP的可视化配置.以及网络服务的重启(注意,这个重启是停止然后启动, 如果使用xshell进行操作会失去ssh连接,直连服务器时可这直接操作).主机 ...
- SSM:Spring整合Mybatis时,连接池和SQLSessionFactory的联系!
- 浅谈Tox之一
本文分享自天翼云开发者社区<浅谈Tox之一>,作者:Moonriver What is tox? tox是通用的virtualenv管理和测试命令行工具,可用于: 使用不同的Python版 ...