poj 1190 搜索+剪枝
2013-07-30 11:37
337 查看
生日蛋糕
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
有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
Output
仅一行,是一个正整数S(若无解则S = 0)。
Sample Input
Sample Output
Hint
圆柱公式
体积V = πR2H
侧面积A' = 2πRH
底面积A = πR2
,太长时间没做搜索了,这道题说句老实话,表示一开始实在没看出来和 搜索 有个毛线的关系,他其实就是用搜索来设置界限,从而优先找到要求解的东西。
这道题剪枝很重要,要不然会超时,包涵下面几类:
如果剩余的最上面几层的最小体积大于剩余需要的体积,那么直接退出:if(minVolume[remainLevel] > remainVolume)
如果当前的面积加上剩余最上面几层的最小面积大于最小面积,那么直接退出:if(currArea + minSurfaceArea[remainLevel] >= minArea)
如果当前层的体积小于剩余层体积平均值,退出当前循环:if(currVolume < remainVolume/remainLevel)
如果当前层的体积大于剩余的体积,进行下一轮循环:if(currVolume > remainVolume)
如果剩余层的最大体积小于需要的体积,那么退出当前循环:if(leftMaxVolume < remainVolume - currVolume)
做到以上的几点即可。
下面是代码:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 12183 | Accepted: 4302 |
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
有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
Output
仅一行,是一个正整数S(若无解则S = 0)。
Sample Input
100 2
Sample Output
68
Hint
圆柱公式
体积V = πR2H
侧面积A' = 2πRH
底面积A = πR2
,太长时间没做搜索了,这道题说句老实话,表示一开始实在没看出来和 搜索 有个毛线的关系,他其实就是用搜索来设置界限,从而优先找到要求解的东西。
这道题剪枝很重要,要不然会超时,包涵下面几类:
如果剩余的最上面几层的最小体积大于剩余需要的体积,那么直接退出:if(minVolume[remainLevel] > remainVolume)
如果当前的面积加上剩余最上面几层的最小面积大于最小面积,那么直接退出:if(currArea + minSurfaceArea[remainLevel] >= minArea)
如果当前层的体积小于剩余层体积平均值,退出当前循环:if(currVolume < remainVolume/remainLevel)
如果当前层的体积大于剩余的体积,进行下一轮循环:if(currVolume > remainVolume)
如果剩余层的最大体积小于需要的体积,那么退出当前循环:if(leftMaxVolume < remainVolume - currVolume)
做到以上的几点即可。
下面是代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; const int inf=1000000000; int leftS[21],leftV[21]; int minS; int V,M; void init(){//一开始脑残了,题目已经说了每个数据都是正整数,我开始没看见,老是没初始化成 memset(leftS,0,sizeof(leftS)); memset(leftV,0,sizeof(leftV)); for(int i=1;i<=20;++i) for(int m=0;m<i;++m){ leftS[i]+=(i-m)*(i-m);; leftV[i]+=(i-m)*(i-m)*(i-m); } } void dfs(int v,int m,int lastR,int lastH,int sumS){ if(m==0&&v==0){ if(sumS<minS){ minS=sumS; } return; } if(leftS[m]+sumS>=minS) return; if(leftV[m]>v) return; int avgV=v/m; for(int r=lastR-1;r>=m;--r) for(int h=lastH-1;h>=m;--h){ int curV=r*r*h; if(curV<avgV) break; if(curV>v) continue; int leftmaxV=0; for(int i=1;i<m;++i){ leftmaxV+=(r-i)*(r-i)*(h-i); } if(v-curV>leftmaxV) break; if(m == M) sumS=r*r; dfs(v-curV,m-1,r,h,sumS+2*r*h); } } int main(){ init(); cin>>V>>M; minS=inf; dfs(V,M,sqrt((double)V)+1,V+1,0); int ans=minS<inf?minS:0; cout<<ans<<endl; return 0; }
相关文章推荐
- POJ 1190 生日蛋糕 搜索加剪枝
- POJ 1190 生日蛋糕 估计最小答案dfs剪枝
- poj 1011 Sticks(经典搜索问题:DFS+剪枝)
- poj1011——剪枝dfs搜索题
- 搜索 + 剪枝 --- POJ 1101 : Sticks
- 搜索 + 剪枝 --- POJ 1101 : Sticks
- poj 1054 The Troublesome Frog (暴力搜索 + 剪枝优化)
- POJ 1190 生日蛋糕(DFS+剪枝)
- 博弈搜索练习-极大极小值搜索+AlphaBeta剪枝--POJ 1085-Triangle War/三角点格棋
- POJ 1416 Shredding Company [暴力搜索 简单剪枝]
- poj 1190 dfs+神剪枝
- POJ-1054 The Troublesome Frog 搜索+剪枝 Or DP+Hash
- POJ 1416Shredding Company(简单搜索技巧和剪枝)
- POJ 1190 生日蛋糕(深搜+剪枝)
- poj 3411 搜索+剪枝
- poj1190 神剪枝啊
- POJ-1190-生日蛋糕-DFS(深搜)-枚举-多重剪枝
- POJ 1011 STICKS 搜索 剪枝
- Network Saboteur POJ - 2531 暴力搜索+剪枝技巧
- poj 1190 生日蛋糕 , 强剪枝