hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***

新模板

  1 /*
  2 HDU 4273 Rescue
  3 给一个三维凸包,求重心到表面的最短距离
  4 模板题:三维凸包+多边形重心+点面距离
  5 */
  6 
  7 #include<stdio.h>
  8 #include<algorithm>
  9 #include<string.h>
 10 #include<math.h>
 11 #include<stdlib.h>
 12 using namespace std;
 13 const int MAXN=550;
 14 const double eps=1e-8;
 15 
 16 struct Point
 17 {
 18     double x,y,z;
 19     Point(){}
 20 
 21     Point(double xx,double yy,double zz):x(xx),y(yy),z(zz){}
 22 
 23     //两向量之差
 24     Point operator -(const Point p1)
 25     {
 26         return Point(x-p1.x,y-p1.y,z-p1.z);
 27     }
 28 
 29     //两向量之和
 30     Point operator +(const Point p1)
 31     {
 32         return Point(x+p1.x,y+p1.y,z+p1.z);
 33     }
 34 
 35     //叉乘
 36     Point operator *(const Point p)
 37     {
 38         return Point(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x);
 39     }
 40 
 41     Point operator *(double d)
 42     {
 43         return Point(x*d,y*d,z*d);
 44     }
 45 
 46     Point operator / (double d)
 47     {
 48         return Point(x/d,y/d,z/d);
 49     }
 50 
 51     //点乘
 52     double  operator ^(Point p)
 53     {
 54         return (x*p.x+y*p.y+z*p.z);
 55     }
 56 };
 57 
 58 struct CH3D
 59 {
 60     struct face
 61     {
 62         //表示凸包一个面上的三个点的编号
 63         int a,b,c;
 64         //表示该面是否属于最终凸包上的面
 65         bool ok;
 66     };
 67     //初始顶点数
 68     int n;
 69     //初始顶点
 70     Point P[MAXN];
 71     //凸包表面的三角形数
 72     int num;
 73     //凸包表面的三角形
 74     face F[8*MAXN];
 75     //凸包表面的三角形
 76     int g[MAXN][MAXN];
 77     //向量长度
 78     double vlen(Point a)
 79     {
 80         return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);
 81     }
 82     //叉乘
 83     Point cross(const Point &a,const Point &b,const Point &c)
 84     {
 85         return Point((b.y-a.y)*(c.z-a.z)-(b.z-a.z)*(c.y-a.y),
 86                      (b.z-a.z)*(c.x-a.x)-(b.x-a.x)*(c.z-a.z),
 87                      (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x)
 88                      );
 89     }
 90     //三角形面积*2
 91     double area(Point a,Point b,Point c)
 92     {
 93         return vlen((b-a)*(c-a));
 94     }
 95     //四面体有向体积*6
 96     double volume(Point a,Point b,Point c,Point d)
 97     {
 98         return (b-a)*(c-a)^(d-a);
 99     }
100     //正:点在面同向
101     double dblcmp(Point &p,face &f)
102     {
103         Point m=P[f.b]-P[f.a];
104         Point n=P[f.c]-P[f.a];
105         Point t=p-P[f.a];
106         return (m*n)^t;
107     }
108     void deal(int p,int a,int b)
109     {
110         int f=g[a][b];//搜索与该边相邻的另一个平面
111         face add;
112         if(F[f].ok)
113         {
114             if(dblcmp(P[p],F[f])>eps)
115               dfs(p,f);
116             else
117             {
118                 add.a=b;
119                 add.b=a;
120                 add.c=p;//这里注意顺序,要成右手系
121                 add.ok=true;
122                 g[p][b]=g[a][p]=g[b][a]=num;
123                 F[num++]=add;
124             }
125         }
126     }
127     void dfs(int p,int now)//递归搜索所有应该从凸包内删除的面
128     {
129          F[now].ok=0;
130          deal(p,F[now].b,F[now].a);
131          deal(p,F[now].c,F[now].b);
132          deal(p,F[now].a,F[now].c);
133     }
134     bool same(int s,int t)
135     {
136         Point &a=P[F[s].a];
137         Point &b=P[F[s].b];
138         Point &c=P[F[s].c];
139         return fabs(volume(a,b,c,P[F[t].a]))<eps &&
140                fabs(volume(a,b,c,P[F[t].b]))<eps &&
141                fabs(volume(a,b,c,P[F[t].c]))<eps;
142     }
143     //构建三维凸包
144     void create()
145     {
146         int i,j,tmp;
147         face add;
148 
149         num=0;
150         if(n<4)return;
151     //**********************************************
152         //此段是为了保证前四个点不共面
153         bool flag=true;
154         for(i=1;i<n;i++)
155         {
156             if(vlen(P[0]-P[i])>eps)
157             {
158                 swap(P[1],P[i]);
159                 flag=false;
160                 break;
161             }
162         }
163         if(flag)return;
164         flag=true;
165         //使前三个点不共线
166         for(i=2;i<n;i++)
167         {
168             if(vlen((P[0]-P[1])*(P[1]-P[i]))>eps)
169             {
170                 swap(P[2],P[i]);
171                 flag=false;
172                 break;
173             }
174         }
175         if(flag)return;
176         flag=true;
177         //使前四个点不共面
178         for(int i=3;i<n;i++)
179         {
180             if(fabs((P[0]-P[1])*(P[1]-P[2])^(P[0]-P[i]))>eps)
181             {
182                 swap(P[3],P[i]);
183                 flag=false;
184                 break;
185             }
186         }
187         if(flag)return;
188     //*****************************************
189         for(i=0;i<4;i++)
190         {
191             add.a=(i+1)%4;
192             add.b=(i+2)%4;
193             add.c=(i+3)%4;
194             add.ok=true;
195             if(dblcmp(P[i],add)>0)swap(add.b,add.c);
196             g[add.a][add.b]=g[add.b][add.c]=g[add.c][add.a]=num;
197             F[num++]=add;
198         }
199         for(i=4;i<n;i++)
200         {
201             for(j=0;j<num;j++)
202             {
203                 if(F[j].ok&&dblcmp(P[i],F[j])>eps)
204                 {
205                     dfs(i,j);
206                     break;
207                 }
208             }
209         }
210         tmp=num;
211         for(i=num=0;i<tmp;i++)
212           if(F[i].ok)
213             F[num++]=F[i];
214 
215     }
216     //表面积
217     double area()
218     {
219         double res=0;
220         if(n==3)
221         {
222             Point p=cross(P[0],P[1],P[2]);
223             res=vlen(p)/2.0;
224             return res;
225         }
226         for(int i=0;i<num;i++)
227           res+=area(P[F[i].a],P[F[i].b],P[F[i].c]);
228         return res/2.0;
229     }
230     double volume()
231     {
232         double res=0;
233         Point tmp(0,0,0);
234         for(int i=0;i<num;i++)
235            res+=volume(tmp,P[F[i].a],P[F[i].b],P[F[i].c]);
236         return fabs(res/6.0);
237     }
238     //表面三角形个数
239     int triangle()
240     {
241         return num;
242     }
243     //表面多边形个数
244     int polygon()
245     {
246         int i,j,res,flag;
247         for(i=res=0;i<num;i++)
248         {
249             flag=1;
250             for(j=0;j<i;j++)
251               if(same(i,j))
252               {
253                   flag=0;
254                   break;
255               }
256             res+=flag;
257         }
258         return res;
259     }
260     //三维凸包重心
261     Point barycenter()
262     {
263         Point ans(0,0,0),o(0,0,0);
264         double all=0;
265         for(int i=0;i<num;i++)
266         {
267             double vol=volume(o,P[F[i].a],P[F[i].b],P[F[i].c]);
268             ans=ans+(o+P[F[i].a]+P[F[i].b]+P[F[i].c])/4.0*vol;
269             all+=vol;
270         }
271         ans=ans/all;
272         return ans;
273     }
274     //点到面的距离
275     double ptoface(Point p,int i)
276     {
277         return fabs(volume(P[F[i].a],P[F[i].b],P[F[i].c],p)/vlen((P[F[i].b]-P[F[i].a])*(P[F[i].c]-P[F[i].a])));
278     }
279 };
280 CH3D hull;
281 int main()
282 {
283    // freopen("in.txt","r",stdin);
284    // freopen("out.txt","w",stdout);
285     while(scanf("%d",&hull.n)==1)
286     {
287         for(int i=0;i<hull.n;i++)
288         {
289             scanf("%lf%lf%lf",&hull.P[i].x,&hull.P[i].y,&hull.P[i].z);
290         }
291         hull.create();
292         Point p=hull.barycenter();
293         double minn=1e20;
294         for(int i=0;i<hull.num;i++)
295         {
296             minn=min(minn,hull.ptoface(p,i));
297         }
298         printf("%.3lf\n",minn);
299     }
300     return 0;
301 }

 

转载于:https://www.cnblogs.com/cnblogs321114287/p/4732583.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM Fighting! 2 1.计算几何 5 1.1 注意 5 1.2几何公式 6 1.3 多边形 8 1.4多边形切割 11 1.5 浮点函数 12 1.6 积 18 1.7球 18 1.8三角形 19 1.9三维几何 22 1.10 凸包 30 1.11 网格 32 1.12 圆 33 1.13 矢量运算求几何模板 35 1.14结构体表示几何图形 47 1.15四城部分几何模板 52 1.16 一些代码 54 1.16.1 最小圆覆盖_zju1450 54 1.16.2 直线旋转_两凸包的最短距离(poj3608) 58 1.16.3 扇形的重心 62 1.16.4 根据经度纬度求球距离 62 1.16.5 多边形的重心 64 1.16.6 存不存在一个平把两堆点分开(poj3643) 66 1.16.7 pku_3335_判断多边形的核是否存在 67 1.16.8 pku_2600_二分+圆的参数方程 74 1.16.9 pku_1151_矩形相交的积 76 1.16.10 pku_1118_共线最多的点的个数 78 1.16.11 pku2826_线段围成的区域可储水量 80 1.16.12 Pick公式 84 1.16.13 N点中三个点组成三角形积最大 86 1.16.14 直线关于圆的反射 89 1.16.15 pku2002_3432_N个点最多组成多少个正方形(hao) 94 1.16.16 pku1981_单位圆覆盖最多点(poj1981)CircleandPoints 97 1.16.17 pku3668_GameofLine_N个点最多确定多少互不平行的直线(poj3668) 99 1.16.18 求凸多边形直径 100 2.组合 102 2.1 组合公式 102 2.2 排列组合生成 102 2.3 生成gray码 104 2.4 置换(polya) 104 2.5 字典序全排列 105 2.6 字典序组合 105 2.7 一些原理及其例子 106 3.数论 108 3.1 阶乘最后非0位 108 3.2 模线性方程组 108 3.3 素数 110 3.4 欧拉函数 114 3.6高精度 116 3.6.1平方根 116 3.6.2 高精度乘幂 117 3.7 高斯消元回代法 122 3.8 数值计算 124 3.8.1 定积分计算 124 3.8.2 多项式求根(牛顿法) 125 3.8.3 周期性方程(追赶法) 127 4.排序 128 4.1快速选择算法 128 4.2归并排序+逆序数的求取 128 5.字符串 130 5.1 KMP应用 130 5.2 后缀数组 131 5.3 中缀表达式转后缀表达式 134 5.4 Firefighters 表达式求值 135 6.博弈 139 6.1 博弈的AB剪枝 139 6.1.1 取石子 139 6.2 博弈 SG函数 局势分割 141 7.数据结构 142 7.1 TRIE 142 7.2 线段树 147 7.3 并查集 151 7.4 树状数组 152 7.5 点树 154 7.6 STL 156 7.7 离散化 157 8.图论 158 8.0 2-SAT 158 8.2 寻找Euler回路 163 8.3 拓扑排序 163 8.4 差分约束系统 164 8.5 笛卡尔树 165 8.6 LCA和RMQ 167 8.7 割和桥 171 8.8 最小生成树(kruskal) 172 8.9 最短路径 173 8.10 最大网络流 175 8.11 最小费用流 180 8.12 最大团问题 182 8.13 二分图匹配 184 8.14 带权的最优二分图匹配 184 9.搜索算法概略 187 9.1 迭代深搜+IDA* 187 9.2 分之界限法(深搜) 189 9.3 A* 8数码问题( pascal ) 192 9.4 优先队列广搜 194 10.应用 197 10.1 Joseph问题 197 10.2 N皇后构造解 197 10.3 布尔母函数 198 10.4 第k元素 199 10.5 幻方构造 199 10.6 模式匹配(kmp) 201 10.7 逆序对数 201 10.8 字符串最小表示 202 10.9 最长公共单调子序列 202 10.10 最长子序列 204 10.11 最大子串匹配 204 10.12 最大子段和 205 10.13 最大子阵和 206 11.其它 207 11.1 大数(只能处理正数) 207 11.2 分数 212 11.3 矩阵 214 11.4 线性方程组 216 11. 5 线性相关 218 11.6 日期 219 11.7 读入 220 11.8 函数 220
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值