搜索(1):剪枝
来源:互联网 发布:php后端是什么 编辑:程序博客网 时间:2024/05/16 12:01
POJ 1190
要制作一个体积为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外,以上所有数据皆为正整数)
·
·
·
分析
·
深度优先搜索,枚举什么?
枚举每一层可能的高度和半径。
·
·
如何确定搜索范围
底层蛋糕的最大可能半径和最大可能高度
·
·
那些地方会体现搜索顺序
从底层往上搭蛋糕,而不是从顶层往下搭 在同一层进行尝试的时候,半径和高度都是从大到小试
·
·
如何剪枝
1:搭建过程中发现已建好的面积已经超过目前求得的最优表面积,或者预见到搭完后面积一定会超过目前最优表面积,则停止搭建 (最优性剪枝)
2:搭建过程中预见到再往上搭,高度已经无法安排,或者半径已经无法安排,则停止搭建(可行性剪枝)
3:搭建过程中发现还没搭的那些层的体积,一定会超过还缺的体积,则停止搭建(可行性剪枝)
4:搭建过程中发现还没搭的那些层的体积,最大也到不了还缺的体积,则停止搭建(可行性剪枝)
·
·
还有什么可以改进
1)用数组存放 MaxVforNRH(n,r,h) 的计算结果,避免重复计算
2)加上对本次Dfs失败原因的判断。如果是因为剩余体积不够大而失败,那么就用不着试下一个高度,直接break; 或者由小到大枚举 h
·
·
代码
#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;int N, M;int minArea = 1 << 30;int area = 0;int minV[30];int minA[30];int minNRH[30][30][30];int MaxVforNRH(int n, int r, int h){ int v = 0; for (int i = 0; i < n; ++i) v += (r - i) *(r - i) * (h - i); return v;}int dfs(int v, int n, int r, int h){ if (n == 0) { if (v) return 0; else { minArea = min(minArea, area); return 0; } } if (v <= 0) return 0; if (minV[n] > v) //剪枝3 return 0; if (area + minA[n] >= minArea) //剪枝1 return 0; if (h < n || r < n) //剪枝2 return 0; if (MaxVforNRH(n, r, h) < v) //剪枝4 //这个剪枝最强!没有的话,5秒都超时,有的话,10ms过! return -1; //for( int rr = n; rr <= r; ++ rr ) 这种写法比从大到小慢5倍 for( int rr = r; rr >=n; -- rr ) { if( n == M ) //底面积 area = rr * rr; for( int hh = h; hh >= n ; --hh ) { int a; area += 2 * rr * hh; a = dfs(v - rr*rr*hh, n - 1, rr - 1, hh - 1); area -= 2 * rr * hh; if (a == -1) break; } }}int main(void){ scanf("%d %d", &N, &M); minV[0] = 0; minA[0] = 0; for (int i = 1; i <= M; i++) { minV[i] = minV[i - 1] + i * i * i; minA[i] = minA[i - 1] + 2 * i * i; } if (minV[M] > N) printf("0\n"); else { int maxH = (N - minV[M - 1]) / (M * M) + 1; int maxR = sqrt((N - minV[M - 1]) / M * 1.0) + 1; area = 0; minArea = 1 << 30; dfs(N, M, maxR, maxH); if (minArea == 1 << 30) printf("0\n"); else printf("%d\n", minArea); } return 0;}
0 0
- 搜索(1):剪枝
- qduoj 分辣条1 (搜索+剪枝)
- poj_1011_sticks(搜索+剪枝)
- hdu4499(剪枝搜索)
- poj1190(搜索剪枝)
- poj1011Sticks(搜索+剪枝)
- poj1190 生日蛋糕 (搜索剪枝)
- poj1011 stick(搜索,剪枝)
- FZU--2188(搜索+剪枝)
- hdu 5305 (搜索+剪枝)
- 搜索(2):估值型剪枝
- POJ 2531(搜索剪枝)
- poj 1011 搜索(剪枝)
- Educational Codeforces Round 1 (D) 搜索(优化剪枝)
- 搜索剪枝
- 搜索剪枝
- 搜索 剪枝
- 搜索剪枝
- PAT 1002. 写出这个数
- 网络最全面的Linux压缩与解压命令大全
- VS2012与win7不兼容的解决办法
- [Cloud Computing]Mechanisms: Virtualization Agent
- 简易手写输入法软件的编写
- 搜索(1):剪枝
- windows 以服务形式启动tomcat(后台启动)
- TortoiseSVN怎么记住这个单词
- (概率DP)正向推概率,反向推期望
- [李景山php]每天laravel-20161002|Validator.php-2
- (模板题)poj 1459 Power Network(Edmonds-Karp算法求最大流)
- python 读取目录下csv文件并绘制曲线v111
- 目前我找过最好的xcode发布app教程
- C#中按汉字的拼音排序建筑物名称