UVALive 4986 Dome of Circus(三分、凸包、凸性函数)
来源:互联网 发布:阿里旺旺网络连接超时 编辑:程序博客网 时间:2024/05/29 18:06
题目链接;
UVALive 4986 Dome of Circus
题意:
在空间中给
数据范围:
分析;
首先把三维的点转成二维的,因为是圆锥覆盖,所以我们只需要知道点到圆锥轴的距离和点的纵坐标就好了。那么可得:
这样子一来我们就把所有的点限制在第一象限内。
我们来考虑当第一象限内的一个点
化简一下可得:
我们带进圆锥的体积公式可得:
我们对
于是我们可以发现
一元可微函数在某个区间上是凸的,当且仅当它的导数在该区间上单调不减。
于是我们可以三分枚举底面圆半径
对于每个点如果
但是我们也可以换个思路。回到最初的问题,我们是想在第一象限内画一条斜率为负的直线,并且假设和横轴、纵轴分别交于
在看看上面的推导根据
我们通过求凸包边和横轴的交点和直线
- 如果是
L1或者L3 ,那么最小圆锥的母线只能选择L - 如果是
L2 ,那么最小圆锥的母线可以选择L2 ,并且这种情况是最优的
我们通过求凸包,枚举凸包边,比较
但是写起来太麻烦了。。。。而且边界情况比较多。
下面的两个代码都是AC了的。
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <climits>#include <cmath>#include <ctime>#include <cassert>#define IOS ios_base::sync_with_stdio(0); cin.tie(0);using namespace std;typedef long long ll;const int MAX_N = 100010;const double eps = 1e-8;int n;inline int sgn(double x) { if(fabs(x) <= eps) return 0; else if(x > 0.0) return 1; else return -1;}struct Point { double x, y; Point() {} Point(double _x, double _y): x(_x), y(_y) {}}point[MAX_N];inline double GetHeight(double r){ double res = -1.0; for(int i = 0; i < n; ++i) { double h = point[i].y * r / (r - point[i].x); if(sgn(h - res) > 0) res = h; } return res;}int main(){ while(~scanf("%d", &n)) { double MinR = -1.0; for(int i = 0; i < n; ++i) { double a, b, c; scanf("%lf%lf%lf", &a, &b, &c); point[i] = Point(sqrt(a * a + b * b), c); if(sgn(point[i].x - MinR) > 0) MinR = point[i].x; } double low = MinR, high = 1e10, mid, midmid, v1, v2; for(int i = 0; i < 100; ++i) { mid = (low + high) / 2.0; midmid = (mid + high) / 2.0; v1 = GetHeight(mid) * mid * mid; v2 = GetHeight(midmid) * midmid * midmid; if(sgn(v2 - v1) < 0) low = mid; else high = midmid; } printf("%.3lf %.3lf\n", GetHeight(mid), mid); } return 0;}
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <climits>#include <cmath>#include <ctime>#include <cassert>#include <vector>#define IOS ios_base::sync_with_stdio(0); cin.tie(0);using namespace std;typedef long long ll;const int MAX_N = 10010;const double eps = 1e-8;inline int sgn(double x) { if(fabs(x) <= eps) return 0; else if(x > 0) return 1; else return -1;}struct Point { double x, y; Point() {} Point(double _x, double _y): x(_x), y(_y) {} Point operator - (const Point& rhs) const { return Point(x - rhs.x, y - rhs.y); } Point operator + (const Point& rhs) const { return Point(x + rhs.x, y + rhs.y); } Point operator * (const double& d) const { return Point(x * d, y * d); } Point operator / (const double& d) const { return Point(x / d, y / d); } double dis(const Point& rhs) const { return sqrt((x - rhs.x) * (x - rhs.x) + (y - rhs.y) * (y - rhs.y)); } double cross(const Point& rhs) const { return x * rhs.y - y * rhs.x; } double dot(const Point& rhs) const { return x * rhs.x + y * rhs.y; }}point[MAX_N], vertex[MAX_N];int n;Point center = Point(0, 0);bool cmp_pola_angle(Point a, Point b){ double res = (a - center).cross(b - center); if(sgn(res) != 0) return sgn(res) > 0; else return a.dis(center) < b.dis(center);}int GetConvex(){ sort(point, point + n, cmp_pola_angle); int k = 0; for (int i = 0; i < n; ++i) { while(k > 1 && sgn((vertex[k - 1] - vertex[k - 2]).cross(point[i] - vertex[k - 1])) <= 0) { k--; } vertex[k++] = point[i]; } int m = k; for (int i = n - 2; i >= 0; --i) { if(k > m && sgn((vertex[k - 1] - vertex[k - 2]).cross(point[i] - vertex[k - 1])) <= 0) { k--; } vertex[k++] = point[i]; } if(k > 1) k--; return k;}inline double GetX(Point a, Point b){ return (a.x * b.y - a.y * b.x) / (b.y - a.y);}inline double GetY(Point a, Point b){ return (a.y * b.x - a.x * b.y) / (b.x - a.x);}int main(){ while(~scanf("%d", &n)) { for(int i = 0; i < n; ++i) { double a, b, c; scanf("%lf%lf%lf", &a, &b, &c); point[i] = Point(sqrt(a * a + b * b), c); } int m = GetConvex(); double r, h, v; if(m == 1) { printf("%.3lf %.3lf\n", 3 * vertex[0].y, 1.5 * vertex[0].x); continue; } else if(m == 2) { if(vertex[0].y > vertex[1].y) swap(vertex[0], vertex[1]); double tmp = GetX(vertex[1], vertex[0]); if(1.5 * vertex[1].x < tmp) { if(1.5 * vertex[0].x >= tmp) { r = tmp, h = GetY(vertex[1], vertex[0]); } else { r = 1.5 * vertex[0].x, h = 3.0 * vertex[0].y; } } else { if(1.5 * vertex[0].x > tmp) { r = 1.5 * vertex[1].x, h = 3.0 * vertex[1].y; } else { double r1 = vertex[0].x * 1.5, h1 = vertex[0].y * 3; double r2 = vertex[1].x * 1.5, h2 = vertex[1].y * 3; if(r1 * r1 * h1 < r2 * r2 * h2) { r = r1, h = h1; } else { r = r2, h = h2; } } } printf("%.3lf %.3lf\n", h, r); continue; } vertex[m] = vertex[0]; double MaxX = -1.0, MaxY = -1.0; int idx, idy; for(int i = 0; i < m; ++i) { if(sgn(vertex[i].x - MaxX) > 0) { MaxX = vertex[i].x; idx = i; } if(sgn(vertex[i].y - MaxY) > 0) { MaxY = vertex[i].y; idy = i; } } if(idx == idy) { printf("%.3lf %.3lf\n", vertex[idx].y * 3.0, vertex[idx].x * 1.5); continue; } double pre, cur, r2, h2, v2; pre = GetX(vertex[(idx + 1) % m], vertex[idx]); if(1.5 * vertex[idx].x <= pre) { r = 1.5 * vertex[idx].x, h = 3.0 * vertex[idx].y; v = r * r * h; } v = 1e20; for(int i = idx + 1; i < idy; ++i) { if(sgn(vertex[i].y - vertex[i - 1].y) < 0) continue; pre = GetX(vertex[i], vertex[i - 1]); cur = GetX(vertex[i + 1], vertex[i]); if(1.5 * vertex[i].x < pre) { r2 = pre, h2 = GetY(vertex[i], Point(pre, 0)); } else if(1.5 * vertex[i].x < cur) { r2 = 1.5 * vertex[i].x, h2 = 3 * vertex[i].y; }else { r2 = cur, h2 = GetY(vertex[i], Point(cur, 0)); } v2 = r2 * r2 * h2; if(sgn(v2 - v) < 0) { v = v2, r = r2, h = h2; } } pre = GetX(vertex[idy], vertex[idy - 1]); if(1.5 * vertex[idy].x >= pre) { r2 = 1.5 * vertex[idy].x, h2 = 3.0 * vertex[idy].y; v2 = r2 * r2 * h2; if(sgn(v2 - v) < 0) { v = v2, r = r2, h = h2; } } else { r2 = pre, h2 = GetY(vertex[idy], Point(pre, 0)); v2 = r2 * r2 * h2; if(sgn(v2 - v) < 0) { v = v2, r = r2, h = h2; } } printf("%.3lf %.3lf\n", h, r); } return 0;}
- UVALive 4986 Dome of Circus(三分、凸包、凸性函数)
- 【三分】HDU3756 Dome of Circus
- Dome of Circus(三分)
- Dome of Circus - UVa 1473 几何 凸包
- LA 4986 hdu3756 Dome of Circus 三分答案
- hdu3756 Dome of Circus:三分学习
- HDU 3756 Dome of Circus 三分
- hdoj 3756 Dome of Circus(三分)
- hdu 3756 三分 Dome of Circus
- hdu 3756 Dome of Circus 三分
- hdu 3756 Dome of Circus 三分
- HDU 3756 Dome of Circus 三分
- HDU 3756 Dome of Circus (三分)
- ACM--steps--4.1.7--Dome of Circus(三分)
- UVA 1473 - Dome of Circus(三分+计算几何)
- HDU 3756 Dome of Circus(计算几何 + 三分)
- HDU Dome of Circus
- LA4986 Dome of Circus
- Codeforces Round #363 (Div. 2)
- Java-Runtime
- 字符数组的翻转
- 深入分析AIL语言及init.rc文件
- 【python单元测试unittest】加载测试套的代码修正
- UVALive 4986 Dome of Circus(三分、凸包、凸性函数)
- 从今天开始写技术博客
- 嵌入式软件开发经典笔试题
- 简述线程
- 设置EditText中输入的密码显示还是不显示?
- 02 微信获取accestoken
- 集合
- Android中的EditText失去和得到焦点时的事件响应
- 泛型