AcWing 168. 生日蛋糕
原题链接:AcWing 168. 生日蛋糕
设当前体积是分别记录每层的高度和半径,由于整个蛋糕的上表面面积等于最大蛋糕的圆面积,所以枚举到最大一层的时候直接加上即可。
-
优化搜索顺序:搜数量小的分支,可以从蛋糕最下边一层开始搜索,因为最下边一层占体积最大,然后对于枚举半径和高度,肯定是先枚举半径,因为它对体积的贡献是平方级别的。
-
上下界剪枝:在第层时,对于与可以求一个范围:
枚举,
枚举
-
可行性剪枝:
预处理出每一层的最小体积和表面积,显然,第层的分别取即可,高度也分别取。那么当当前加到层的大于那么直接返回。 -
最优性剪枝:
如果当前表面积加上到层的,那么就剪枝。 -
最优性剪枝:
利用和数组,到层的体积可以表示为 ,1到depth - 1层的表面积可以表示为。利用放缩法,,所以当大于已经搜到的答案时,可以剪枝。
// Problem: 生日蛋糕
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/170/
// Memory Limit: 10 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
const int N = 25, INF = 1E9;
int n, m;
int R[N], H[N];
int res = INF;
int minv[N], mins[N];
void dfs(int u, int v, int s) {
if (v + minv[u] > n) return;
if (s + mins[u] >= res) return;
if (s + 2 * (n - v) / R[u + 1] >= res) return;
//说明已经从上往下搜到了最后一层
if (!u) {
if (v == n) res = s;
return;
}
for (int r = min(R[u + 1] - 1, (int)sqrt(n - v)); r >= u; r--) {
for (int h = min(H[u + 1] - 1, (n - v) / r / r); h >= u; h--) {
int t = 0;
if (u == m) t = r * r;
R[u] = r, H[u] = h;
dfs(u - 1, v + r * r * h, s + 2 * r * h + t);
}
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= m; i++) {
minv[i] = minv[i - 1] + i * i * i;
mins[i] = mins[i - 1] + i * i * 2;
}
R[m + 1] = H[m + 1] = INF;
dfs(m, 0, 0);
if (res == INF) res = 0;
cout << res << endl;
return 0;
}
分类:
之前的比赛题目 / 算法从0开始
标签:
DFS
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端