ACM hdu5432 Pyramid Split
2015-09-16 13:22
323 查看
题目连接:
http://acm.hdu.edu.cn/showproblem.php?pid=5432一道非常水的题目,,首先让我们来分析一下,答案拥有确定的范围,也就是拥有确定的最大最小值,粗粗一看,可以肯定范围在0到最高的金字塔高度之间,然后没有别的可以利用的条件,而这种情况下的解题策略就非常明了,推导体积公式,然后二分搜索,因为体积与高度是线性关系而非曲线。
代码如下:
#include <iostream> #include <string.h> using namespace std; double h[10001];//本来是int就可以,但是不希望发生强制转换使用了double,虽然在acm中可能不太要紧,但在编程中强制转换有可能导致类型不安全,应尽量避免 double s[10001]; double getTargetVolume(int numOfTower)//返回我们目标的体积,但并不是总体积的一半,因为我根据公式做了一点分母的改变,棱锥体积公式中含有一些常量,我将v*3将其化为1 { double V=0; for (int i = 1; i <= numOfTower;++i) { V += (1.0 / 3.0)* h[i] * s[i] * s[i]; } return V *3.0 / 2.0; } inline double equation(double p, int idx)//对应每一个高度,每个金字塔被切割后的体积,如上,依据公式的不同,不同人会在这里加上不同的常量 { if (p >= h[idx]) return 0.0; double ret = (h[idx] - p)*(h[idx] - p)*(h[idx] - p); return ret*s[idx] * s[idx] / (h[idx] * h[idx]); } int BinarySearch(double head, double tail, double target,int num)//教科书一般的,二分搜索 { double p; double volume; while (tail-head>1e-5) { p = (head + tail) / 2; volume = 0; for (int i = 1; i <= num; ++i) volume += equation(p, i); if (volume > target) head = p; else if (volume < target) tail = p; else return p; } return p; } int main() { int T; scanf("%d", &T); int n; double tail; while (T--) { cin >> n; tail = 0; for (int i = 1; i <= n;++i) { scanf("%lf", &h[i]);//注意,不要用cin,cout,由于数据量的关系会超时,博主由于使用cin,cout而超时了3,4次 if (h[i] > tail) tail = h[i]; } for (int i = 1; i <= n;++i) { scanf("%lf", &s[i]); } int ans = BinarySearch(0, tail, getTargetVolume(n), n); printf("%d\n", ans); } return 0; }
相关文章推荐
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- C++二分查找在搜索引擎多文档求交的应用分析
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例
- PHP实现克鲁斯卡尔算法实例解析