您的位置:首页 > 其它

poj1190——生日蛋糕

2017-11-20 21:17 260 查看
题目大意:制作一个每层都是圆柱体,体积Nπ的M层蛋糕,下层的比上层的半径更大,高度更高,找出每层适当的Ri和Hi使得蛋糕表面积(最下一层的下底面除外)Sπ最小,求S的最小值,以上数据皆为正整数
输入:N(N <= 10000)
           M(M <= 20)
输出:S(若无解输出0)
分析:dfs+花式大剪枝
           剪枝方法如下:
           1.半径r,与高h都从N+1开始搜索。           2.因为前level层的面积为s,如果剩下的几层的面积都取最小可能值,所得的面积和比已经得到的所求的最小面积best大,也可以进行剪枝(剪枝条件为:s+mins[dep-1]>best)           3.因为前level层的体积为v,如果剩下的几层的体积都取最小可能值,总体积还是比n大,那么则说明前level层的方案不可行,所以可以剪枝(剪枝条件为:v+minv[dep-1]>n)            4.(目前体积-已有体积)/r*2+已有的表面积若大于已经得到过的S则减掉。           /***2*r*h=S* r*r*h=V* => V*2/r = S* S + sumS >= best => return;*/如果把剩下的所有体积,全部用来只做成一个圆柱体,这种情况加所增加到表面积是最小的。 
代码:转载自http://blog.csdn.net/v5zsq/article/details/46575215
#include<stdio.h>
#define in(a,b) (a<b?a:b)
int n,m;
int minv[21],mins[21];
int bests;

void dfs(int v,int s,int level,int r,int h)//v为体积,s为表面积,level为搜索深度,从底层m层向上搜,r,h分别为level的上一层的半径和高度
{
if(level==0)//搜索完成,则更新最小面积值
{
if(v==n&&s<bests)
bests=s;
return ;
}
if(v+minv[level-1]>n||s+mins[level-1]>bests||2*(n-v)/r+s>=bests)//剪枝
return ;
int i,j,hh;
for(i=r-1;i>=level;i--)//按递减顺序枚举level层蛋糕半径的每一个可能值,这里第level层的半径最小值为level
{
if(level==m)//底面积作为外表面积的初始值(总的上表面积,以后只需计算侧面积)
s=i*i;
hh=in((n-v-minv[level-1])/(i*i),h-1); //最大高度,即level层蛋糕高度的上限,(n-v-minv[level-1])表示第level层最大的体积
for(j=hh;j>=level;j--)//同理,第level层的最小高度值为level
dfs(v+i*i*j,s+2*i*j,level-1,i,j);//递归搜索子状态
}
}
int main()
{
int i;
minv[0]=0;
mins[0]=0;
for(i=1;i<=20;i++)//从顶层向下计算出最小体积和表面积的可能值
{
//从顶层(即第一层)到第i层的最小体积minv[i]成立时第j层的半径和高度都是j
minv[i]=minv[i-1]+i*i*i;
mins[i]=mins[i-1]+2*i*i;
}
while(scanf("%d%d",&n,&m)==2)
{
bests=0x7fffffff;
dfs(0,0,m,n+1,n+1);
if(bests==0x7fffffff)
printf("0\n");
else
printf("%d\n",bests);
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: