vijos 生日蛋糕
来源:互联网 发布:淘宝同城交易怎么弄 编辑:程序博客网 时间:2024/05/02 00:15
描述
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为N*pi的M层生日蛋糕,每层都是一个圆柱体。 设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri > Ri+1且Hi > Hi+1。 由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。 令Q = S*pi 请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。(除Q外,以上所有数据皆为正整数)
格式
输入格式
每组数据两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为N*pi;第二行为M(M <= 20),表示蛋糕的层数为M。
输出格式
仅一行,是一个正整数S(若无解则S=0)。
样例1
样例输入1
100
2
样例输出1
68
来源
NOIP99
//生日蛋糕-Milky#include<cstdio>#include<cmath>using namespace std;int V,N,vmin[10005],smin[10005],ans=0x7fffffff;void dfs(int i,int r,int h,int snow,int vnow){ for(int ri=r-1; ri>=N-i+1; --ri) for(int hi=N-i+1; hi<h; ++hi) { int s0=2*ri*hi,v0=ri*ri*hi; if(i==1) snow=ri*ri; if(snow+s0+smin[i+1]<ans&&vnow+v0+vmin[i+1]<=V&&vnow+v0+(N-i)*v0>=V) { if(i==N) ans=snow+s0; else dfs(i+1,ri,hi,snow+s0,vnow+v0); } }}int main(){ scanf("%d%d",&V,&N); for(int i=1;i<=N;++i) { vmin[N-i+1] = vmin[N-i+2] + i*i*i; smin[N-i+1] = smin[N-i+2] + 2*i*i; } int max_r1=sqrt((V-vmin[2])/N); int max_h1=(V-vmin[2])/(N*N); dfs(1,max_r1+1,max_h1+1,0,0); if(ans==0x7fffffff) ans=0; printf("%d\n",ans); return 0;}
代码很短,思路能看出来。
为什么半径倒搜,高度正搜呢?
由于除了最底层以外,每一层蛋糕的表面积都是侧面积,求侧面积的公式是 2*r*h。
我们再回到代码14行,s0=2*ri*hi,v0=ri*ri*hi
。
在 s 中,r 和 h 的增长都是线性的;v 中,r 的增长是平方的,h 相应的减小也是平方的。因此 r 越大,h 越以平方性减小,所以在相同的 v 下,得到的 s 就越小。
所以半径倒搜,高度正搜,可以更快地找到最优解。在此之后的搜索都会被剪枝,效率更高。
题解中还有一个思路,加上以后剪枝更严格,效率更高,
上面已经证明,当体积一定时,半径越大,侧面积越小。假设剩余的蛋糕层都和当前层一样,r 都为当前 r,这样 r 就是最大的了,如果计算所得侧面积与当前面积之和大于等于最优解,退出。
- vijos 生日蛋糕
- Vijos P1297 生日蛋糕 NOI1999
- 生日蛋糕
- 生日蛋糕
- 生日蛋糕
- 生日蛋糕
- 生日蛋糕
- 生日蛋糕!
- 生日蛋糕
- 生日蛋糕
- 生日蛋糕(noi99)
- PKU1190 生日蛋糕
- pku1190 生日蛋糕
- POJ_1190_生日蛋糕
- 1068 生日蛋糕
- UVA10167 生日蛋糕
- poj1190 生日蛋糕
- poj1190生日蛋糕
- vue项目搭建步骤
- [k8s]kube-dns架构图解
- 【jzoj1617】【SCOI2005】【互不侵犯】【状态压缩动态规划】
- 点击弹出div层带遮罩可拖动和关闭层
- 【RTL-SDR】用RTL-SDR实现航班追踪(ADS-B)
- vijos 生日蛋糕
- 数组中单独元素问题
- Revit二次开发建立程序:在类库中添加WPF
- SD卡的控制方法与时序
- Colorful Graph CodeForces
- poj
- Python语法基础01.注释
- spring boot 教程(六)多数据源配置与使用
- java结束线程的三种方法