hdu 4266 The Worm in the Apple 三维凸包
来源:互联网 发布:dota2解除小黑屋软件 编辑:程序博客网 时间:2024/05/20 05:54
The Worm in the Apple
Time Limit: 50000/20000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 540 Accepted Submission(s): 248
Problem Description
Willy the Worm was living happily in an apple – until some vile human picked the apple, and started to eat it! Now, Willy must escape!
Given a description of the apple (defined as a convex shape in 3D space), and a list of possible positions in the apple for Willy (defined as 3D points), determine the minimum distance Willy must travel to get to the surface of the apple from each point.
Given a description of the apple (defined as a convex shape in 3D space), and a list of possible positions in the apple for Willy (defined as 3D points), determine the minimum distance Willy must travel to get to the surface of the apple from each point.
Input
There will be several test cases in the input. Each test case will begin with a line with a single integern (4≤n≤1,000), which tells the number of points describing the apple.
On the next n lines will be three integers x, y and z (-10,000≤x,y,z≤10,000), where each point (x,y,z) is either on the surface of, or within, the apple. The apple is the convex hull of these points. No four points will be coplanar.
Following the description of the apple, there will be a line with a single integerq (1≤q≤100,000), which is the number of queries – that is, the number of points where Willy might be inside the apple. Each of the followingq lines will contain three integers x, y and z (-10,000≤x,y,z≤10,000), representing a point (x,y,z) where Willy might be. All of Willy’s points are guaranteed to be inside the apple. The input will end with a line with a single 0.
On the next n lines will be three integers x, y and z (-10,000≤x,y,z≤10,000), where each point (x,y,z) is either on the surface of, or within, the apple. The apple is the convex hull of these points. No four points will be coplanar.
Following the description of the apple, there will be a line with a single integerq (1≤q≤100,000), which is the number of queries – that is, the number of points where Willy might be inside the apple. Each of the followingq lines will contain three integers x, y and z (-10,000≤x,y,z≤10,000), representing a point (x,y,z) where Willy might be. All of Willy’s points are guaranteed to be inside the apple. The input will end with a line with a single 0.
Output
For each query, output a single floating point number, indicating the minimum distance Willy must travel to exit the apple. Output this number with exactly 4 decimal places of accuracy, using standard 5 up / 4 down rounding (e.g. 2.12344 rounds to 2.1234, 2.12345 rounds to 2.1235). Output each number on its own line, with no spaces, and do not print any blank lines between answers.
Sample Input
60 0 0100 0 00 100 00 0 10020 20 2030 20 1041 1 130 30 357 8 990 2 20
Sample Output
1.00002.88687.00002.0000
Source
The University of Chicago Invitational Programming Contest 2012
#include<stdio.h>#include<string.h>#include<math.h>#include<algorithm>#include<vector>using namespace std;const int eps = 1e-8;const int N = 1010;struct Point{ double x, y, z; Point(double x = 0, double y = 0, double z = 0): x(x), y(y), z(z){} void Read(){ scanf("%lf%lf%lf", &x, &y, &z); } Point operator - (const Point &p) const{ return Point(x - p.x, y - p.y, z - p.z); } Point operator * (const Point &p) const{ return Point(y * p.z - z * p.y, z * p.x - x * p.z, x * p.y - y * p.x); }//叉积 double operator ^ (const Point &p) const{ return x * p.x + y * p.y + z * p.z; }//点积};struct fac{ int a,b,c; //凸包一个面上的三个点的编号 bool ok; //该面是否是最终凸包中的面};struct T3dhull{ int n;//初始点数 Point ply[N];//初始点 int trianglecnt;//凸包上三角形数 fac tri[N];//凸包三角形 int vis[N][N];//点i到点j是属于哪个面 double dist(Point a){ return sqrt(a.x * a.x + a.y * a.y + a.z * a.z); }//点距原点的距离 double area(Point &a, Point &b, Point &c){ return dist( (b - a) * ( c - a ) ); }//三角形面积*2 double volume(Point &a, Point &b, Point &c, Point &d){ return (b - a) * (c - a) ^ (d - a); }//四面体有向体积*6 double Point_surface_direction(Point &p, fac &f){ Point m = ply[f.b] - ply[f.a]; Point n = ply[f.c] - ply[f.a]; Point t = p - ply[f.a]; return ( m * n ) ^ t; }//正:点在面同向 double Point_surface_dis(Point &p, fac &f){ Point m = ply[f.a] - ply[f.b]; Point n = ply[f.b] - ply[f.c]; Point t = p - ply[f.a]; double ans = ((m * n) ^ t) / dist(m * n); return fabs(ans); }// 计算点到面的距离 double Point_hull_dismin(Point &p){ double ans = 210000; for(int i = 0; i < trianglecnt; i++){ double tp = Point_surface_dis(p, tri[i]); ans = min(ans, tp); } return ans; } void deal(int p, int a, int b){ int f = vis[a][b];//与当前面(cnt)共边(ab)的那个面 fac add; if(tri[f].ok) { if((Point_surface_direction(ply[p],tri[f]))>eps) dfs(p,f);//如果p点能看到该面f, //则继续深度探索f的3条边,以便更新新的凸包面 else//否则因为p点只看到cnt面,看不到f面,则p点和a、b点组成一个三角形。 { add.a = b; add.b = a; add.c = p; add.ok = 1; vis[p][b] = vis[a][p] = vis[b][a] = trianglecnt; tri[trianglecnt++] = add; } } } void dfs(int p,int cnt)//维护凸包,如果点p在凸包外更新凸包 { tri[cnt].ok=0;//当前面需要删除,因为它在更大的凸包里面//下面把边反过来(先b,后a),//以便在deal()中判断与当前面(cnt)共边(ab)的那个面。//即判断与当头面(cnt)相邻的3个面(它们与当前面的共边是反向的,//如下图中(1)的法线朝外(即逆时针)的面130和312,它们共边13,但一个方向是13,//另一个方向是31) deal(p,tri[cnt].b,tri[cnt].a); deal(p,tri[cnt].c,tri[cnt].b); deal(p,tri[cnt].a,tri[cnt].c); } bool same(int s,int e)//判断两个面是否为同一面 { Point a = ply[tri[s].a], b = ply[tri[s].b], c = ply[tri[s].c]; return fabs(volume(a,b,c,ply[tri[e].a])) < eps &&fabs(volume(a,b,c,ply[tri[e].b])) < eps &&fabs(volume(a,b,c,ply[tri[e].c])) < eps; } void construct()//构建凸包 { int i,j; trianglecnt = 0; if(n < 4) return ; bool tmp = true; for(int i = 1; i < n; i++)//前两点不共点 { if((dist(ply[0] - ply[i])) > eps) { swap(ply[1],ply[i]); tmp = false; break; } } if(tmp) return; tmp=true; for(int i = 2; i < n; i++)//前三点不共线 { if((dist((ply[0]-ply[1]) * (ply[1]-ply[i]))) > eps) { swap(ply[2],ply[i]); tmp=false; break; } } if(tmp) return ; tmp = true; for(int i = 3; i < n; i++)//前四点不共面 { if(fabs((ply[0]-ply[1]) * (ply[1]-ply[2]) ^ (ply[0]-ply[i])) > eps) { swap(ply[3],ply[i]); tmp = false; break; } } if(tmp) return ; fac add; for(int i = 0; i < 4; i++) //构建初始四面体(4个点为ply[0],ply[1],ply[2],ply[3]) { add.a = (i + 1) % 4; add.b = (i + 2) % 4; add.c = (i + 3) % 4; add.ok = 1; if((Point_surface_direction(ply[i], add)) > 0) swap(add.b,add.c); //保证逆时针,即法向量朝外,这样新点才可看到。 vis[add.a][add.b] = vis[add.b][add.c] = vis[add.c][add.a] = trianglecnt;//逆向的有向边保存 tri[trianglecnt++] = add; } for(int i = 4; i < n; i++)//构建更新凸包 { for(int j = 0; j < trianglecnt; j++) //对每个点判断是否在当前3维凸包内或外(i表示当前点,j表示当前面) { if(tri[j].ok && (Point_surface_direction(ply[i],tri[j])) > eps) //对当前凸包面进行判断,看是否点能否看到这个面 { dfs(i,j); break;//点能看到当前面,更新凸包的面(递归, //可能不止更新一个面)。当前点更新完成后break跳出循环 } } } int cnt = trianglecnt; //这些面中有一些tri[i].ok=0, //它们属于开始建立但后来因为在更大凸包内故需删除的, //所以下面几行代码的作用是只保存最外层的凸包 trianglecnt = 0; for(int i = 0; i < cnt; i++){ if(tri[i].ok) tri[trianglecnt++] = tri[i]; } }// double area()//表面积// {// double ret=0;// for(int i=0;i<trianglecnt;i++)// ret+=area(ply[tri[i].a],ply[tri[i].b],ply[tri[i].c]);// return ret/2;// }// double volume()//体积// {// TPoint p(0,0,0);// double ret=0;// for(int i=0;i<trianglecnt;i++)// ret+=volume(p,ply[tri[i].a],ply[tri[i].b],ply[tri[i].c]);// return fabs(ret/6);// } int facetri() { return trianglecnt; }//表面三角形数 int pointcnt(){ vector<int>ans; for(int i = 0; i < trianglecnt; i++){ ans.push_back(tri[i].a); ans.push_back(tri[i].b); ans.push_back(tri[i].c); } sort(ans.begin(), ans.end()); return unique(ans.begin(), ans.end()) - ans.begin(); }// 返回凸包的定点数 int facepolygon()//表面多边形数 { int ans = 0; for(int i = 0; i < trianglecnt; i++) { int k = 1; for(int j = 0; j < i; j++) { if(same(i,j)){ k = 0; break; } } ans += k; } return ans; }}hull;int main(){// freopen("in.in","r",stdin); while(~scanf("%d",&hull.n)){ if(hull.n == 0) break; for(int i = 0; i < hull.n; i++) hull.ply[i].Read(); hull.construct(); int Que; scanf("%d", &Que); Point p; for(int q = 0; q < Que; q++){ p.Read(); printf("%.4f\n", hull.Point_hull_dismin(p)); } } return 0;}
0 0
- HDU 4266 The Worm in the Apple(三维凸包)
- hdu 4266 The Worm in the Apple 三维凸包
- HDU 4266 The Worm in the Apple
- HDU 4266 The Worm in the Apple(三维凸包内点到表面距离)
- hdu 4266 The Worm in the Apple (线段树)
- HDU 4573 Throw the Stones 三维凸包模版应用
- hdu 2782 The Worm Turns
- HDU 2782 The Worm Turns (DFS)
- sgu290:Defend the Milky Way(三维凸包)
- zoj1056 The Worm Turns
- The Worm Turns
- 1056The Worm Turns
- ZOJ1056 The Worm Turns
- The Happy Worm(poj1974)
- FOJ1176 The Happy Worm
- The Happy Worm
- The Worm Turns
- The Worm Turns
- 挑战面试编程:原码、反码、补码
- Linux 进程间通信 --- 信号通信 --- signal --- signal(SIGINT, my_func); --- 按键驱动异步通知
- 黑马程序员--详解希尔排序
- 20140920 【 线段树 — 区间覆盖,区间查询 】 2014 ACM/ICPC Asia Regional Guangzhou Online--A Corrupt Mayor's Perfor
- HttpUrlConnection使用总结
- hdu 4266 The Worm in the Apple 三维凸包
- android Intent 显示和隐示意图
- iOS8 Core Image In Swift:视频实时滤镜
- 自己实现C语言双向向链表
- iOS8 UILabel BUG ? text不显示
- sip服务器搭建
- nyoj 40 公约数和公倍数
- 在ViewPaper中获取Fragment对象
- 分数拆分