NOI题库192 生日蛋糕
2015-11-04 15:14
330 查看
192:生日蛋糕
总时间限制:
5000ms
内存限制:
65536kB
描述
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i <
M时,要求Ri > Ri+1且Hi > Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q = Sπ
请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。
(除Q外,以上所有数据皆为正整数)
输入
有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
输出
仅一行,是一个正整数S(若无解则S = 0)。
样例输入
100
2
样例输出
68
提示
圆柱公式
体积V = πR2H
侧面积A' = 2πRH
底面积A = πR2
来源
Noi 99
【思路】
搜索+剪枝。
依次搜索每一层的高度与半径。三个剪枝策略如下:
【代码】
总时间限制:
5000ms
内存限制:
65536kB
描述
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i <
M时,要求Ri > Ri+1且Hi > Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q = Sπ
请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。
(除Q外,以上所有数据皆为正整数)
输入
有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
输出
仅一行,是一个正整数S(若无解则S = 0)。
样例输入
100
2
样例输出
68
提示
圆柱公式
体积V = πR2H
侧面积A' = 2πRH
底面积A = πR2
来源
Noi 99
【思路】
搜索+剪枝。
依次搜索每一层的高度与半径。三个剪枝策略如下:
//这里用到的三个剪枝 //sums + mins[deep]> best 表示以前的到的deep + 1层到 m 层的表面积加上从顶层到deep层的最小表面积如果都大于了已经得到的best,那么1到deep层是无论半径和高度取何值都是无效的 //sumv + minv[deep] > n同理 // 2 * (n - sumv) / r + sums >= best 这是该题的精髓,如果没有的话会造成超时,是为了把sumv和sums联系起来,原因如下: // 假设能够得到best时(为什么这样假设呢,因为如果得不到的话那么就已经被第一个剪枝滤去了,所以在第三个剪枝验证时表示已经通过了第一个剪枝的要求), // n - sumv = h[1] * r[1] * r[1] + ... + h[deep] * r[deep] * r[deep] < h[1] * r[1] * r + ... + h[deep] * r[deep] * r (因为r是deep + 1层的半径) //其中h[1]...h[deep]表示在函数的形参情况下,1到deep层应该取得h值,r[1]同理 // 两边同时处以r 再乘以2得 2 * (n - sumv) / r < 2 * (h[1] * r[1] + ... + h[deep] * r[deep]) // 2 * (n - sumv) / r < best - sums // 2 * (n - sumv) / r + sums < best 成立 ,则可得剪枝条件
【代码】
#include<iostream> #include<cmath> using namespace std; using namespace std; const int maxn = 20+5; const int INF=1e9; int minv[maxn],mins[maxn]; int n,m,ans; void init() { for(int i=1;i<=m;i++) { minv[i]=minv[i-1]+i*i*i; mins[i]=mins[i-1]+2*i*i; } } void dfs(int dep,int v,int r,int h,int S) { if(!dep) { if(v==n&&S<ans) ans=S; return ; } if(S+mins[dep]>ans || v+minv[dep]>n ||(2 * (n - v) / r + S >= ans) ) return ; for(int nowr=r-1;nowr>=dep;nowr--) { if(dep==m) S=nowr*nowr; int maxh=min(h-1,n-v-minv[dep-1]/nowr*nowr); for(int nowh=maxh;nowh>=dep;nowh--) { dfs(dep-1,v+nowr*nowr*nowh,nowr,nowh,S+2*nowr*nowh); } } } int main() { cin>>n>>m; init(); ans=INF; dfs(m,0,sqrt(n),n+1,0); //当只有一层时得到 R H 上限 if(ans==INF) cout<<0; else cout<<ans; return 0; }
相关文章推荐
- 如何使用JVisualVM进行性能分析
- 你应该成为 Web 开发者的 5 大理由—兄弟连IT教育
- CentOS 下对 Nginx + Tomcat 配置 SSL 实现服务器 / 客户端双向认证
- CentOS6.5最小化安装包选择
- 数据结构与算法
- iOS学习之OC语法基础-类和对象-什么是类
- Python变量类型
- Android目录介绍&UI简介
- Pixhawk控制电机命令pwm源码详解
- 【HDOJ】1254 推箱子
- hadoop的文件压缩
- struct2源码解读(2)之struct2初始化
- [LeetCode]Binary Tree Zigzag Level Order Traversal
- Some solutions for simple errors/exceptions when setting up Spring
- 使用JavaScript和CSS实现文本隔行换色的方法
- [LeetCode]Binary Tree Zigzag Level Order Traversal
- Android:Layout_weight的深刻理解
- 在iOS中扫描银行卡得到 银行卡的基本信息,暂时只支持 建行
- oracle创建表中LONG字段类型的使用注意事项
- 编译链接boost库