1710 生日蛋糕(1999 noi)

1999年NOI全国竞赛

题目描述 Description

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外,以上所有数据皆为正整数)

输入描述 Input Description

有两行,第一行为N(N<=10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M<=20),表示蛋糕的层数为M。

输出描述 Output Description

仅一行,是一个正整数S(若无解则S=0)。

样例输入 Sample Input

100   2

样例输出 Sample Output

68

数据范围及提示 Data Size & Hint

体积V=πR2H

侧面积A’=2πRH

底面积A=πR2

题目分析:搜索题,其实不减枝的代码还是很好写的。

参考程序:

#include<stdio.h>

#include<string.h>

#define maxn 22

#define INF 100000000

int N,M,ans,maxh;

//m为蛋糕的层数, v为当前的体积, s为当前得到的面积,r和h为当前层的半径和高

void dfs(int m,int v,int s,int r,int h){

//退出条件

if(m == 0){

if(ans > s && v == N) ans = s;

return;

}

//枚举可能的解

for(int i = r-1; i >= m; i--){

for(int j = maxh; j >= m; j--){

if(m == M) s = i * i;

dfs(m-1,v+i*i*j,s+2*i*j,i,j);

}

}

}

int main(){

scanf("%d%d",&N,&M);

ans = INF;

maxh=N/M/M;//唯一的剪枝,底层蛋糕的最大高度N/(M*M)

dfs(M,0,0,N+1,N+1);

if(ans == INF) printf("0\n");

else printf("%d\n",ans);

return 0;

}

然后就是剪枝呢,四个减枝的条件:

先打表,算出每层蛋糕的最小体积和表面积(minv[i]和mins[i]),然后在来减枝

1、v+minv[m]  > V

v为已经涂的体积,那么如果v加上下一层最小的体积比总体积V还大,这显然是不可能的,减去。

2、s+min[m] > ans

s为已经涂的面积,那么s加上下一次最小的面积比当前求得的ans还大,显然不需要dfs了,减去。

3、2*(V-v)/r + s >= ans

已经涂了s,那么还剩下rest_s = sum{2*Ri*Hi} >= sum{2*Ri*Ri*Hi/Rk} = 2*(V-v)/r (设k为当前层的半径)。如果rest_s加上s大于等于ans,那么也不用在dfs了。

4、maxh = Min((N-v-minv[m-1])/(i*i),h-1)

当枚举半径为i时,当前最低的可能高为maxh = Min((N-v-minv[m-1])/(i*i),h-1)。

剪枝后的代码:

//注意:本程序蛋糕自顶向下编号(与题目相反),dfs由下向上运行.

#include<iostream>

#include<cmath>

using namespace std;

const int INF=1000000;

const int Size=22;

int N,M;

int ans;

int mins[Size],minv[Size];

int maxh;

void init(){

mins[0]=minv[0]=0;

for(int i=1;i<=M;i++){

mins[i]=mins[i-1]+2*i*i;

minv[i]=minv[i-1]+i*i*i;

}

}

void dfs(int m,int v,int s,int lastr,int lasth){

//cout<<m<<' ';

if(m==0){

if(v==N)ans=min(ans,s);

return;

}

if(v+minv[m]>N)return;

if(s+mins[m]>=ans)return;

if(2*(N-v)/lastr+s>=ans)return;

for(int r=lastr-1;r>=m;r--){

int maxh=min((N-v-minv[m-1])/(r*r),lasth-1);//注意这里是minv[m-1],因为 总体积N – 已经有的v – 将要有的最小体积minv[m+1]  才是 m这一层的最大体积,进而计算最大高度

//cout<<maxh<<endl;

for(int h=maxh;h>=m;h--){

if(m==M)s=r*r;//整个蛋糕与桌面向平的那些环面的面积之和==底层蛋糕的圆面的面积,在此加上

dfs(m-1,v+r*r*h,s+2*r*h,r,h);

}

}

}

int main(){

freopen("1.in","r",stdin);

cin>>N>>M;

ans=INF;

maxh=N/M/M;

init();

int maxr=sqrt(N);

dfs(M,0,0,maxr+1,N+1);

cout<<ans<<endl;

return 0;

}

1710 生日蛋糕(1999 noi)的更多相关文章

  1. 初赛Part1

    计算机硬件 CPU CPU(中央处理器) = 运算器(ALC) + 控制器 + 寄存器, 主要任务是执行数据运算和程序控制. CPU的主要性能指标包括主频, 字长 ,高速缓存容量, 指令集等. 主频 ...

  2. 解题:NOI 1999 生日蛋糕

    题面 裸的搜索题,就说剪枝(注:nw->noww->当前,res->rest->剩余): 1.想达到$Nπ$的体积,那么半径一开始最多也就$sqrt(n)$了,再大就超了... ...

  3. NOI题库192 生日蛋糕

    192:生日蛋糕 总时间限制: 5000ms 内存限制: 65536kB 描述 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体. 设从下往上数第i ...

  4. 生日蛋糕 (codevs 1710) 题解

    [问题描述] 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1<=i<=M)层蛋糕是半径为Ri,高度为Hi的圆柱 ...

  5. Codevs 1710 == POJ 1190 生日蛋糕 == 洛谷P1731

    生日蛋糕 时间限制: 2 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ ...

  6. 【题解】NOI 系列题解总集

    每次做一道 NOI 系列的估计都很激动吧,对于我这种萌新来说( P1731 [NOI1999]生日蛋糕 练习剪枝技巧,关于剪枝,欢迎看我的垃圾无意义笔记 这道题是有一定难度的,需要运用各种高科技剪枝( ...

  7. POJ1190生日蛋糕[DFS 剪枝]

    生日蛋糕 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18236   Accepted: 6497 Description ...

  8. POJ 1190 生日蛋糕 【DFS + 极限剪枝】

    题目传送门:http://poj.org/problem?id=1190 参考剪枝:https://blog.csdn.net/nvfumayx/article/details/6653111 生日蛋 ...

  9. POJ1190 洛谷P1731 NOI1999 生日蛋糕

    生日蛋糕(蛋糕是谁?) Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20272   Accepted: 7219 Desc ...

随机推荐

  1. FPGA设计者必须精通的5项基本功

    FPGA设计者的5项基本功:仿真.综合.时序分析.调试.验证. 对于FPGA设计者来说,练好这5项基本功,与用好相应的EDA工具是同一过程,对应关系如下: 1. 仿真:Modelsim, Quartu ...

  2. java代码-----indexOf()方法--从字符串的某个字符的第一次出现的位子开始

    总结:方法是indedOf()方法.this  is my sister   //indexOf()方法是indexOf('m')==7 .那么就是字符m第一次出现的位置是顺数第7个,就会正常显示‘t ...

  3. 1、Window.document对象

    1.Window.document对象 一.找到元素: docunment.getElementById("id"):根据id找,最多找一个:    var a =docunmen ...

  4. Redis:目录

    ylbtech-Redis:目录 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   7.返回顶部   8.返回顶部   9.返回顶部   ...

  5. AD域中客户端时间与服务器同步

    1.域控配置 修改注册表,设置域控服务器名称 设置组策略,启动NTP服务器 域策略中设置windows time服务自动启动 2.客户端 更新域策略gpupdate /force 如果不重启的话,先n ...

  6. java 检测代理IP是否准确

    我这里提供2个方法都可以实现:第一个是createIPAddress()和convertStreamToString() import java.io.IOException; import java ...

  7. 关于模拟admin实现stark组件的知识点

    一. url知识 还记得include分发么?里面的参数都可以有些什么? urlconf_module本质是返回的是模块路径对象 def include(arg, namespace=None, ap ...

  8. Shell教程快速入门

    Shell即是一种命令语言,又是一种程序设计语言,使用者可以通过Shell访问操作系统的内核服务. Shell编程和java.python.C一样,只要一个能编写代码的文本编辑器和一个能解释执行的脚本 ...

  9. 【BZOJ】2160: 拉拉队排练(Manacher)

    题目 2160: 拉拉队排练 Description 艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了.拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛.所以作为拉拉队队长 ...

  10. mysql数据安全一之数据恢复案例

    mysql数据安全一之数据恢复案例 --chenjianwen 应用场景:适宜开启binlog 日志功能,定时备份并使用--master-data参数备份,在某个时间点丢失数据,用于数据恢复 开篇总结 ...