HDU 4573 Throw the Stones(动态三维凸包)(2013 ACM-ICPC长沙赛区全国邀请赛)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4573

Problem Description

  Remember our childhood? A few naked children throw stones standing on the same position, the one throws farther win the game. Aha, of course, there are some naughty boys who care more about whether they can urinate father.
  You believe it or not, anyway, I believed. Nowadays, some of the children are smarter than we were, while others may be more naughty.
  A week ago, I saw several children throw stones. In fact, they are more clever than we were, since the game they played, apparently, is more complex than we did. Maybe you have different points of view, however, you’d better learn about the rules of the game before expressing your views. A group of children take turns to throw stones standing on the same position. After some child throw a stone, the children will draw a convex polyhedron with smallest volume together to enclose all the stones thrown by them. You may assume that the stone is so small as to be abstracted as a point in three-dimensional space. Naively, the children regard the space enclosed by the convex polyhedron as territory under their control. After a child throw his stone, the score he obtains equals the incremental of the volume of their territory.   Unfortunately, the first three child’s score will always be zero. At last, the child with the highest score will win the game, and known as the "King".
  I think you have accepted my opinion already, for the rules of their throwing stones game are really complicated. But, you also don’t need to be frustrated for it. Now, in order to show you are smarter, maybe you can write a program to help the children point out their "King".

Input

  Input consists of a number of cases. The data of each case appears on a number of input lines, the first of which contains an integer N. The following N lines contain three number (xi, yi, zi) indicating coordinates of the stone thrown by the i-th child. 
Note: 1 <= N <= 10^4, 1 <= i <= N, -10^4 <= xi , yi , zi <= 10^4.

Output

  For each test case, you should output two lines. The first line is "Case #K:", K means the number of the test case. The second line is "i v", i means index of the "King" and v means the score of the "King". If there are more than one "King", output the one throws stone earlier than others.
  Please round the result to 2 digits after decimal point if necessary.

题目大意:给一个三维空间点集依次加入N个点,形成一个三维凸包。问加入哪一个点的时候,凸包的体积增量最大,即前 i 个点组成的凸包体积减去前 i - 1个点组成的凸包体积最大。输出这个点,并输出这个增量。

思路:http://blog.csdn.net/catalyst1314/article/details/9017673

PS:我的代码框架几乎都是照着上面写的。但是怎么看内存都会超出限制,虽然不知道为什么实际上没有(我算错了?),虽说现场没有这种限制。然后不知为何说时间复杂度是O(n*sqrt(n)),我怎么觉得最坏情况下还是O(n^2)的……

代码(531MS):

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <cmath>
  6 using namespace std;
  7 typedef long long LL;
  8
  9 const int MAXN = 10001;
 10 const double EPS = 1e-9;
 11
 12 inline int sgn(double x) {
 13     return (x > EPS) - (x < -EPS);
 14 }
 15
 16 struct Point {
 17     double x, y, z;
 18     Point() {}
 19     Point(double x, double y, double z): x(x), y(y), z(z) {}
 20     void read() {
 21         scanf("%lf%lf%lf", &x, &y, &z);
 22     }
 23     Point operator - (const Point &rhs) const {
 24         return Point(x - rhs.x, y - rhs.y, z - rhs.z);
 25     }
 26     double operator * (const Point &rhs) const {
 27         return x * rhs.x + y * rhs.y + z * rhs.z;
 28     }
 29 };
 30 double length(const Point &a) {
 31     return sqrt(a * a);
 32 }
 33 Point cross(const Point &a, const Point &b) {
 34     Point res;
 35     res.x = a.y * b.z - a.z * b.y;
 36     res.y = a.z * b.x - a.x * b.z;
 37     res.z = a.x * b.y - a.y * b.x;
 38     return res;
 39 }
 40 Point cross(const Point &o, const Point &a, const Point &b) {
 41     return cross(a - o, b - o);
 42 }
 43 double volume(const Point &a, const Point &b, const Point &c, const Point &d) {
 44     return cross(c - a , b - a) * (d - a) / 6;
 45 }
 46 Point p[MAXN];
 47
 48 struct Face {
 49     int a, b, c;
 50     bool flag;
 51     Face() {}
 52     Face(int a, int b, int c, bool flag): a(a), b(b), c(c), flag(flag) {}
 53     bool can_see(const Point &q) {
 54         return sgn(volume(p[a], p[b], p[c], q)) > 0;
 55     }
 56 };
 57 Face fac[MAXN * 10];
 58
 59 struct Convex {
 60     double diff_vol;
 61     int cnt, mat[MAXN][MAXN];
 62
 63     void init() {
 64         cnt = 0;
 65         for(int i = 0; i < 4; ++i) {
 66             Face newf = Face((i + 1) % 4, (i + 2) % 4, (i + 3) % 4, true);
 67             if(newf.can_see(p[i])) swap(newf.a, newf.c);
 68             mat[newf.a][newf.b] = mat[newf.b][newf.c] = mat[newf.c][newf.a] = cnt;
 69             fac[cnt++] = newf;
 70         }
 71     }
 72
 73     void restore(int k, int a, int b) {
 74         int f = mat[a][b];
 75         if(fac[f].flag) {
 76             if(fac[f].can_see(p[k])) dfs(k, f);
 77             else {
 78                 mat[b][a] = mat[a][k] = mat[k][b] = cnt;
 79                 fac[cnt++] = Face(b, a, k, true);
 80             }
 81         }
 82     }
 83
 84     void dfs(int k, int f) {
 85         diff_vol += volume(p[fac[f].a], p[fac[f].b], p[fac[f].c], p[k]);
 86         fac[f].flag = false;
 87         restore(k, fac[f].b, fac[f].a);
 88         restore(k, fac[f].c, fac[f].b);
 89         restore(k, fac[f].a, fac[f].c);
 90     }
 91
 92     double update(int k) {
 93         diff_vol = 0;
 94         for(int i = 0; i < cnt; ++i) {
 95             if(!fac[i].flag || !fac[i].can_see(p[k])) continue;
 96             dfs(k, i);
 97             break;
 98         }
 99         return diff_vol;
100     }
101
102     double vol() {
103         double res = 0;
104         for(int i = 0; i < cnt; ++i) if(fac[i].flag)
105             res -= volume(p[fac[i].a], p[fac[i].b], p[fac[i].c], Point(0, 0, 0));
106         return res;
107     }
108 } solver;
109
110 int n, kase;
111
112 void solve() {
113     int king = 0;
114     double maxans = 0;
115     for(int i = 1, tmp = 1; i < n; ++i) {
116         if(tmp == 1) {
117             tmp += sgn(length(p[0] - p[i]));
118             if(tmp > 1) swap(p[1], p[i]);
119         } else if(tmp == 2) {
120             tmp += sgn(length(cross(p[0], p[1], p[i])));
121             if(tmp > 2) swap(p[2], p[i]);
122         } else if(tmp == 3) {
123             tmp += (sgn(volume(p[0], p[1], p[2], p[i])) != 0);
124             if(tmp > 3) {
125                 swap(p[3], p[i]);
126                 solver.init();
127                 for(int j = 4; j <= i; ++j) solver.update(j);
128                 king = i, maxans = solver.vol();
129             }
130         } else {
131             double v = solver.update(i);
132             if(sgn(v - maxans) > 0) {
133                 maxans = v;
134                 king = i;
135             }
136         }
137     }
138     printf("%d %.2f\n", king + 1, maxans);
139 }
140
141 int main() {
142     while(scanf("%d", &n) != EOF) {
143         for(int i = 0; i < n; ++i) p[i].read();
144         printf("Case #%d:\n", ++kase);
145         solve();
146     }
147 }

HDU 4573 Throw the Stones(动态三维凸包)(2013 ACM-ICPC长沙赛区全国邀请赛)

时间: 2024-08-26 12:24:10

HDU 4573 Throw the Stones(动态三维凸包)(2013 ACM-ICPC长沙赛区全国邀请赛)的相关文章

Hdu 3662 3D Convex Hull(三维凸包)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3662 思路:三维凸包模板. #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define PR 1e-8 #define N 510 using namespace std; struct TPoint { doub

HDU 5874 Friends and Enemies 【构造】 (2016 ACM/ICPC Asia Regional Dalian Online)

Friends and Enemies Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 291    Accepted Submission(s): 160 Problem Description On an isolated island, lived some dwarves. A king (not a dwarf) ruled t

hdu 5023 &amp;&amp; poj 2777(线段染色)2014 ACM/ICPC Asia Regional 广州 Online

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5023 http://poj.org/problem?id=2777 题意:给出一个长度为N的线段,分成N段,每一段长度为1,每次操作时,把[L, R]区间染成颜色C,或者输出[L, R]区间里有几种不同的颜色. 分析:因为N比较大,如果模拟操作肯定会超时.这时我们就可以利用线段树的lazy思想来进行求解. #include<cstdio> #include<cstring> #inc

HDU 5438 Ponds (拓扑排序+DFS)2015 ACM/ICPC Asia Regional Changchun Online

[题目链接]:click here~~ [题目大意]: 题意:在一个无向图中有 p 个点, m 条边,每个点有一个值 vi .不断的删去度数小于2的点直到不能删为止.求新图中所有点个数为奇数的连通分量的点值的和. 1<p<10^4,1<m<10^5 [思路]删边考虑类似拓扑排序的写法,不过topsort是循环一遍1到n结点入度为0的结点,然后加入到队列中,这里只要改一下度数小于等于1,最后DFS 判断一下 挫挫的代码: /* * Problem: HDU No.5438 * Run

hdu 4431 第37届ACM/ICPC 天津赛区现场赛A题 枚举

题意:就是给了13张牌.问增加哪些牌可以胡牌.m是数字,s是条,p是筒,c是数字 胡牌有以下几种情况: 1.一个对子 +  4组 3个相同的牌或者顺子.  只有m.s.p是可以构成顺子的.东西南北这样的牌没有顺子. 2.7个不同的对子. 3.1m,9m,1p,9p,1s,9s,1c,2c,3c,4c,5c,6c,7c.  这13种牌每种都有,而且仅有这13种牌.肯定是有一种2张.其他的1张. 模拟即可,第一个对子的情况需要枚举 很麻烦的模拟,但是貌似稳银的很需要这题,所以这种难度必须要弄懂,加油

hdu 5038 Grade(简单模拟求解)2014 ACM/ICPC Asia Regional 北京 Online

Grade                                                                     Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Problem Description Ted is a employee of Always Cook Mushroom (ACM). His boss Matt gives h

HDU 5901 Count primes (1e11内的素数个数) -2016 ICPC沈阳赛区网络赛

题目链接 题意:求[1,n]有多少个素数,1<=n<=10^11.时限为6000ms. 官方题解:一个模板题, 具体方法参考wiki或者Four Divisors. 题解:给出两种代码. 第一种方法Meisell-Lehmer算法只需265ms. 第二种方法不能运行但是能AC,只需35行. 第一种: //Meisell-Lehmer #include<cstdio> #include<cmath> using namespace std; #define LL long

hdu 4462 第37届ACM/ICPC 杭州赛区 J题

题意:有一块n*n的田,田上有一些点可以放置稻草人,再给出一些稻草人,每个稻草人有其覆盖的距离ri,距离为曼哈顿距离,求要覆盖到所有的格子最少需要放置几个稻草人 由于稻草人数量很少,所以状态压缩枚举,之后慢慢判断即可,注意放稻草人的格子是不需要覆盖的 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath>

hdu 4461 第37届ACM/ICPC杭州赛区I题

题意:给两个人一些棋子,每个棋子有其对应的power,若b没有或者c没有,或者二者都没有,那么他的total power就会减1,total power最少是1,求最后谁能赢 如果b或c出现的话,flag就标记为1,那么在判断的时候如果flag==0,就说明他们没出现过,那么就要-1,然后就wa了,必须要两个变量判断,不知道为什么 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #inclu