POJ 1190 生日蛋糕 (dfs + 神剪枝)
2016-03-29 16:17
447 查看
POJ 1190
有三处剪枝,作为渣渣表示这题对我来说很有难度。题解也是看了好久才理解。
首先,minv[i] 表示从上往下数第i层以及第i层以上的最小总体积,mins[i]表示从上往下数第i层以及第i层以上的最小总面积。仔细想想可以知道每层的半径和高度都取这一层的层数即可得到最小值。
然后具体见代码。
参考博客:/article/4912093.html 感谢!是我看过的最严谨最好理解的版本
有三处剪枝,作为渣渣表示这题对我来说很有难度。题解也是看了好久才理解。
首先,minv[i] 表示从上往下数第i层以及第i层以上的最小总体积,mins[i]表示从上往下数第i层以及第i层以上的最小总面积。仔细想想可以知道每层的半径和高度都取这一层的层数即可得到最小值。
然后具体见代码。
参考博客:/article/4912093.html 感谢!是我看过的最严谨最好理解的版本
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; int N, M; const int inf = 0x3f3f3f3f; int minv[25], mins[25]; int ans; void dfs(int r, int h, int layer, int v, int s) { if(layer == 0) { if(v == N && ans > s) ans = s; return; } if(N - v < minv[layer]) return;//剪枝1:总体积减去蛋糕当前层以下的层的总体积 //小于上面的层所能构成的最小体积 if(ans - s < mins[layer]) return;//剪枝2:当前得到的最优解减去蛋糕当前层以下的层的总面积 //小于上面的层所能构成的最小面积 if(s + 2 * (N - v) / r > ans) return;//剪枝3:2 * (N - v) / r 表示剩下的体积能组成最小面积 //的极限情况,可以证明,同样的体积组成一个大圆柱体和组成 //多个比一个大圆柱体小的小圆柱体相比,前者的表面积比后者 //要小,所以这种表面积最小的情况再加上本层以下的确定的表 //面积s如果是大于已知最优解s,那么最终结果一定不会比ans小 //返回 。(难理解) int i, j; for(i = r; i >= layer; i--) { if(layer == M) s = i * i; //第一次要加上底面的面积 int maxh = min(h, (N - v - minv[layer - 1]) / i / i); //后者为本层高度最高的情况, //但再高也不能高过最高高度h for(j = maxh; j >= layer; j--) { dfs(i - 1, j - 1, layer - 1, v + i * i * j, s + 2 * i * j); } } } int main() { int i; minv[0] = mins[0] = 0; for(i = 1; i <= 20; i++) { minv[i] = minv[i - 1] + i * i * i; mins[i] = mins[i - 1] + 2 * i * i; } while(~scanf("%d %d", &N, &M)) { ans = inf; dfs((int)sqrt(N), N, M, 0, 0); //第一和第二个参数分别指最大的半径和最大的高度 if(ans == inf) printf("0\n"); else printf("%d\n", ans); } return 0; }
相关文章推荐
- ORM框架分析之DB到Entity的映射(四)
- get与post区别
- linux--文件--/etc/passwd多了一个/etc/passwd-文件
- 欢迎使用CSDN-markdown编辑器
- AngularJS浅谈
- linux下的串口通信
- java中值类型与引用类型
- 安装CleanMyMac 3提示软件已损坏
- 欢迎使用CSDN-markdown编辑器
- unique函数
- matlab图像处理
- JAVA正则表达式语法大全
- PHP 缩放图片
- HDU 1402 FFT
- ImageView的scaleType属性
- Android 代码实现国内和国外的区分
- iOS数据存储之CoreData封装MagicalRecord
- MySQL权限篇之SHUTDOWN及SUPER还有TRIGGER
- 提高php编程效率的53个小知识点
- 华为机考 给你一个N*M的矩阵,每个位置的值是0或1,求一个面积最大的子矩阵,这个矩阵必须是一个正方形,且里面只能由1构成,输出最大的正方形边长。其中n,m<=400;