hdu 3756 || Dome of Circus || 2010 Northeastern European Regional Contest(三分)
2015-08-04 00:24
423 查看
题目hdu 3756 Dome of Circus连接 请搓
题意:
在建一个已原点为圆心的圆锥体。要求圆锥体要包括在给出n个在第一、二、三、四象限的所有点,并且使圆锥体体积最小,求出半径和高。
思路:
看了这个百度搜索排第一题解看懂了内容,但是这个和具体实现没太大关系,头都大了。一怒写下这个自以为比较简单粗暴的博客。
其实求最小体积,只和两个变量有关,即圆半径 r 和圆锥高 h, 而所求体积是正比于: r * r * h,这样只需要计算出 r * r * h的最小值并且输出 r 和 h 即可。
由与最后结果的圆体至少会和一个点相交,而点固定的话,r大则h小而体积 v 越大, 反之,r 小 h 大 v 也大,所以在一定范围内存在一个峰值(即所求答案),没错,要对 r 进行三分,每个三分的值需要对每个点计算h,取最大的h和r^2相乘得到体积,然后继续三分,知道得到答案。又由 x、y、z 的范围都不超过 1000,所以范围是[max_r, 1e4] max_r是所有点的离轴的距离中最大的,而10000的确定。。。想不出就去补数学去。
复杂度:
时间复杂度:O(n * 2 * lg3(10000-marx_r))
空间复杂度:O(n)
代码
题意:
在建一个已原点为圆心的圆锥体。要求圆锥体要包括在给出n个在第一、二、三、四象限的所有点,并且使圆锥体体积最小,求出半径和高。
思路:
看了这个百度搜索排第一题解看懂了内容,但是这个和具体实现没太大关系,头都大了。一怒写下这个自以为比较简单粗暴的博客。
其实求最小体积,只和两个变量有关,即圆半径 r 和圆锥高 h, 而所求体积是正比于: r * r * h,这样只需要计算出 r * r * h的最小值并且输出 r 和 h 即可。
由与最后结果的圆体至少会和一个点相交,而点固定的话,r大则h小而体积 v 越大, 反之,r 小 h 大 v 也大,所以在一定范围内存在一个峰值(即所求答案),没错,要对 r 进行三分,每个三分的值需要对每个点计算h,取最大的h和r^2相乘得到体积,然后继续三分,知道得到答案。又由 x、y、z 的范围都不超过 1000,所以范围是[max_r, 1e4] max_r是所有点的离轴的距离中最大的,而10000的确定。。。想不出就去补数学去。
复杂度:
时间复杂度:O(n * 2 * lg3(10000-marx_r))
空间复杂度:O(n)
代码
/* *********************************************** Author :Ilovezilian Created Time :2015/8/3 21:02:56 File Name :d.cpp ************************************************ */ #include <bits/stdc++.h> #define fi(i,n) for(int i = 0; i < n; i ++) #define fin(i,n1,n2) for(int i = n1; i < n2; i ++) #define ll long long #define INF 0x7fffffff using namespace std; const int N = 10010, mod = 1e9+7; struct point{ double x, y, z, r; } p ; int n; double cal(double r) { double m = 0; fi(i,n) m = max(m, p[i].z / (r - p[i].r)); return m * r; } void solve() { scanf("%d", &n); double mh, mr; mh = mr = 0; fi(i,n) { scanf("%lf%lf%lf", &p[i].x, &p[i].y, &p[i].z); p[i].r = sqrt(p[i].y * p[i].y + p[i].x * p[i].x); mr = max(mr, p[i].r); mh = max(mh, p[i].z); } double r = 2 * 1e+3, l = mr, midl, midr, la, ra; while(r - l > 1e-4) { midl = (r + 2 * l) / 3, midr = (l + 2 * r) / 3; la = cal(midl) * midl * midl, ra = cal(midr) * midr * midr; if(la < ra) r = midr; else l = midl; } double ans = (r + l) / 2; printf("%.3f %.3f\n", cal(ans), ans); } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int cas; scanf("%d", &cas); while(cas --) solve(); return 0; }
相关文章推荐
- HDU 4349 Xiao Ming's Hope 组合数学
- Linux小知识
- Android应用架构
- hbase 列族优化 ,shell 管理集群
- 小练习:用socket实现Linux和Windows之间的通信
- wkhtmltopdf:一个 Linux 中将网页转成 PDF 的智能工具
- 在Linux下如何修改Mysql的用户(root)的密码
- JS脚本根据手机浏览器类型跳转WAP手机网站(两种方式)
- log4j.properties 的使用详解
- Linux的一些命令
- 外网访问自己的tomcat
- rpmbuild in Docker
- CentOS下打包
- 虚ip设置
- Linux下时间同步
- Linux命令
- Linux C/C++编程手册查阅方法
- 支付宝钱包系统架构内部剖析(架构图)
- shell路由查询脚本
- ha-2:read-project-properties (default) on project