文章目录
The Worm in the Apple【三维凸包内一点到凸包表面的最短距离】
题意:求三维凸包内一点到凸包表面的最短距离。
思路:最优解一定存在于点到凸包面所在平面的距离中。
证明:
-
根据点在平面上的投影是否落在凸包面内,可将凸包面分为两种。
-
假设点在凸包面A所在平面的投影落在外面,那一定存在某相邻凸包面B,使得两平面夹角大于90°。
-
过此点和两投影点作横截面,发现dis(点,凸包面A) < dis(点,凸包面所在平面) < dis(点,相邻凸包面B)
-
因此点到第一种凸包面的距离总小于到第二种凸包面的距离。枚举点到所有平面距离即可。
拓展:三维凸包外一点到凸包表面的最短距离不满足以上性质,最优解也可能位于凸包棱上。
AC代码:http://acm.hdu.edu.cn/viewcode.php?rid=36763472
Throw the Stones【询问最大增量】
题意:询问增量过程中最大增量。
未AC代码:
de不出来bug,de不出来bug,de不出来bug
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<bitset>
using namespace std;
typedef long long LL;
const int N = 1e4 + 10;
const double eps = 1e-12;
double rand_eps() { return ((double)rand() / RAND_MAX - 0.5) * eps; }
struct point{
double x, y, z;
void shake() { x += rand_eps(); y += rand_eps(); z += rand_eps(); }
}P[N];
point operator + (point a, point b) { return {a.x + b.x, a.y + b.y, a.z + b.z}; }
point operator - (point a, point b) { return {a.x - b.x, a.y - b.y, a.z - b.z}; }
point cross(point a, point b) { return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x}; }
double dot(point a, point b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
double length(point a) { return sqrt(a.x * a.x + a.y * a.y + a.z * a.z); }
double volume(point a, point b, point c, point d) { return dot(cross(b - a, c - a), d - a); }
struct plane{
int v[3];
point norm() { return cross(P[v[1]] - P[v[0]], P[v[2]] - P[v[0]]); }
double area() { return length(norm()) / 2; }
bool above(point a) { return dot(a - P[v[0]], norm()) >= 0; }
}E[N], tmp[N];
int n, m;
bitset<N>g[N];
double ans;
int id;
void get_convex_3d()
{
m = 0;
E[m++] = {0, 1, 2}; E[m++] = {2, 1, 0};
double last = 0;
for(int i=3; i<n; i++)
{
int cnt = 0;
for(int j=0; j<m; j++)
{
bool t = E[j].above(P[i]);
if(!t) tmp[cnt++] = E[j];
for(int k=0; k<3; k++)
g[E[j].v[k]][E[j].v[(k + 1) % 3]] = t;
}
for(int j=0; j<m; j++)
for(int k=0; k<3; k++)
{
int a = E[j].v[k], b = E[j].v[(k + 1) % 3];
if(g[a][b] && !g[b][a]) tmp[cnt++] = {a, b, i};
}
m = cnt;
for(int j=0; j<m; j++) E[j] = tmp[j];
double now = 0;
for(int j=0; j<m; j++) now += volume(P[E[j].v[0]], P[E[j].v[1]], P[E[j].v[2]], {0, 0, 0});
now = fabs(now);
if(ans < now - last) ans = now - last, id = i + 1, last = now;
}
}
int main()
{
int T = 1;
while(scanf("%d", &n)!=EOF)
{
for(int i=0; i<n; i++)
{
scanf("%lf %lf %lf", &P[i].x, &P[i].y, &P[i].z);
P[i].shake();
}
ans = 0;
get_convex_3d();
printf("Case #%d:\n%d %.2f\n", T++, id, ans / 6);
}
return 0;
}