poj_1190_剪枝训练
2016-03-14 23:14
218 查看
生日蛋糕
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
/*************************
思路:把所有可能罗列出来,得到最小表面积。做题过程中要考虑从哪里开始,到哪里结束;
也就是说要考虑到初始状态和结束状态,而每次搜索状态的改变都会对应改变一些变量的值,
1.这些变量往往就是搜索时要着重考虑的。
比如加在函数中dfs(int a,int b,int c,int d),
比如每次搜索中sum++或minS = min(minS,nowS);
2.深搜重在一个深字,一条路走到底,所以每次搜索 初始化 和 回溯 也很重要
PS:一开始竟然超时,后来根据高人指点加了剪枝5,神剪枝啊
*************************/
一开始编写的时候在遍历搜索里写错了 dfs,把
maxR, maxH
仍然按照主函数的方法写,但是输出值总是比标准答案小,后来想到是没有考虑到:
m-1
层的半径用这种方式计算可能比m层的半径大。。。那样很可能形成的是一个类似菱形旋转形成的几何体或是什么乱七八糟的东西。。。
因此乖乖在搜索中用
r-1, h-1
进一步搜索。。。
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 16428 | Accepted: 5836 |
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
/*************************
思路:把所有可能罗列出来,得到最小表面积。做题过程中要考虑从哪里开始,到哪里结束;
也就是说要考虑到初始状态和结束状态,而每次搜索状态的改变都会对应改变一些变量的值,
1.这些变量往往就是搜索时要着重考虑的。
比如加在函数中dfs(int a,int b,int c,int d),
比如每次搜索中sum++或minS = min(minS,nowS);
2.深搜重在一个深字,一条路走到底,所以每次搜索 初始化 和 回溯 也很重要
PS:一开始竟然超时,后来根据高人指点加了剪枝5,神剪枝啊
*************************/
<span style="font-size:14px;">#include <cstdio> #include <cstdlib> #include <iostream> #include <stack> #include <queue> #include <algorithm> #include <cstring> #include <cmath> #include <vector> #include <bitset> #include <list> using namespace std; #define INT_MAX 1 << 30 typedef long long ll; int N,M; int Vmin[30]; int Smin[30]; int maxR,maxH; int minV; int nowV; int minS; int nowS; int maxV(int nn,int rr,int hh) { int vv = 0; for (int i = 0; i < nn; i += 1) { vv += (rr-i)*(rr-i)*(hh-i); } return vv; } void dfs(int v, int m, int maxR, int maxH) { if ((m == 0) && (v == 0)) //循环结束条件判断 { minS = min(minS,nowS); return ; } if ((v <= 0) || (m <= 0)) //剪枝2,其中一值为负则跳出 { return ; } if (nowV >= N) //剪枝3,第一层未搜完便溢出,跳出 { return ; } if (nowS >= minS) //剪枝4,第一层未搜完便溢出,跳出 { return ; } if(maxV(m,maxR,maxH) < v) //剪枝5,不仅考虑溢出,还要考虑不足 { return ; } for (int r = maxR; r >= m; r -= 1) //遍历循环 { for (int h = maxH; h >= m; h -= 1) { if (m == M) { nowS = r*r; nowV = 0; } nowS += 2*r*h; //下次循环初始化 nowV += r*r*h; dfs(v-r*r*h,m-1,r-1,h-1); //循环 nowS -= 2*r*h; //回溯 nowV -= r*r*h; } } } int main() { cin >> N >> M; //输入及存储 Smin[0] = M*M; Vmin[0] = 0; minV = 0; for (int i = 0; i <= M; i += 1) { Vmin[i] += i*i*i; Smin[i] = Smin[i-1] + 2*i*i; } if(Vmin[M] > N) //剪枝1 printf("0\n"); else { int H = (N-Vmin[M-1])/(M*M) + 1; int R = (int)sqrt((double)((N-Vmin[M-1])/M))+1; minS = (1 << 30); //初始化 dfs(N,M,R,H); //搜索 printf("%d\n",minS); //输出 } return 0; }</span>
一开始编写的时候在遍历搜索里写错了 dfs,把
maxR, maxH
仍然按照主函数的方法写,但是输出值总是比标准答案小,后来想到是没有考虑到:
m-1
层的半径用这种方式计算可能比m层的半径大。。。那样很可能形成的是一个类似菱形旋转形成的几何体或是什么乱七八糟的东西。。。
因此乖乖在搜索中用
r-1, h-1
进一步搜索。。。
相关文章推荐
- 搜狗百度360市值齐跌:搜索引擎们陷入集体焦虑?
- 本人即将筹备败家日志,敬请期待!
- IE:使用搜索助手
- C++深度优先搜索的实现方法
- 基于文本的搜索
- php实现搜索一维数组元素并删除二维数组对应元素的方法
- 使用Sphinx对索引进行搜索
- asp 多关键词搜索的简单实现方法
- C#使用foreach语句搜索数组元素的方法
- WordPress中用于获取搜索表单的PHP函数使用解析
- JavaScript中数组的排序、乱序和搜索实现代码
- jquery ztree实现树的搜索功能
- C#编程实现Excel文档中搜索文本内容的方法及思路
- sqlserver中在指定数据库的所有表的所有列中搜索给定的值
- 可以用来搜索当前页面内容的js代码
- 全文搜索和替换
- javascript搜索自动提示功能的实现第1/3页
- iOS应用中UISearchDisplayController搜索效果的用法
- mysql 模糊搜索的方法介绍
- C#搜索文字在文件及文件夹中出现位置的方法