欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1209


题目概括

  给出立体的n个点。求三维凸包面积。


题解

  增量法,看了一天,还是没有完全懂。

  上板子!


代码

  1. #include <cstring>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstdlib>
  5. #include <cmath>
  6. #include <vector>
  7. #include <ctime>
  8. using namespace std;
  9. const double Eps=1e-8;
  10. const int N=100+5;
  11. int Dcmp(double x){
  12. if (fabs(x)<Eps)
  13. return 0;
  14. return x<0?-1:1;
  15. }
  16. struct Point{
  17. double x,y,z;
  18. Point (){}
  19. Point (double x_,double y_,double z_){
  20. x=x_,y=y_,z=z_;
  21. }
  22. }P[N],p[N];
  23. Point operator - (Point a,Point b){
  24. return Point(a.x-b.x,a.y-b.y,a.z-b.z);
  25. }
  26. Point operator + (Point a,Point b){
  27. return Point(a.x+b.x,a.y+b.y,a.z+b.z);
  28. }
  29. Point operator * (Point a,double x){
  30. return Point(a.x*x,a.y*x,a.z*x);
  31. }
  32. Point operator / (Point a,double x){
  33. return Point(a.x/x,a.y/x,a.z/x);
  34. }
  35. Point cross(Point a,Point b){
  36. return Point(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
  37. }
  38. Point cross(Point a,Point b,Point c){
  39. return cross(b-a,c-a);
  40. }
  41. double Dot(Point a,Point b){
  42. return a.x*b.x+a.y*b.y+a.z*b.z;
  43. }
  44. double Length(Point P){
  45. return sqrt(Dot(P,P));
  46. }
  47. double rand01(){
  48. return (double)rand()/(double)RAND_MAX;
  49. }
  50. double randEps(){
  51. return (rand01()-0.5)*Eps;
  52. }
  53. Point add_noise(Point P){
  54. return Point(P.x+randEps(),P.y+randEps(),P.z+randEps());
  55. }
  56. struct Face{
  57. int v[3];
  58. Face(){}
  59. Face(int a,int b,int c){
  60. v[0]=a,v[1]=b,v[2]=c;
  61. }
  62. Point Normal(Point *P){
  63. return cross(P[v[0]],P[v[1]],P[v[2]]);
  64. }
  65. int CanSee(Point *P,int i){
  66. return Dot(P[i]-P[v[0]],Normal(P))>0?1:0;
  67. }
  68. };
  69. struct ConvexHull{
  70. vector <Face> cur;
  71. bool vis[N][N];
  72. void Increment(Point *P,int n){
  73. vector <Face> next;
  74. memset(vis,0,sizeof vis);
  75. for (int i=1;i<=n;i++)
  76. P[i]=add_noise(P[i]);
  77. cur.clear();
  78. cur.push_back(Face(1,2,3));
  79. cur.push_back(Face(3,2,1));
  80. for (int i=4;i<=n;i++){
  81. next.clear();
  82. for (int j=0;j<cur.size();j++){
  83. Face F=cur[j];
  84. int res=F.CanSee(P,i);
  85. if (!res)
  86. next.push_back(F);
  87. for (int k=0;k<3;k++)
  88. vis[F.v[k]][F.v[(k+1)%3]]=res;
  89. }
  90. for (int j=0;j<cur.size();j++)
  91. for (int k=0;k<3;k++){
  92. int a=cur[j].v[k],b=cur[j].v[(k+1)%3];
  93. if (vis[a][b]&&!vis[b][a])
  94. next.push_back(Face(a,b,i));
  95. }
  96. cur=next;
  97. }
  98. }
  99. double Area(Point a,Point b,Point c){
  100. return 0.5*Length(cross(a,b,c));
  101. }
  102. double Area(Face F,Point *P){
  103. return Area(P[F.v[0]],P[F.v[1]],P[F.v[2]]);
  104. }
  105. double Area(Point *P){
  106. double Answer=0;
  107. for (int i=0;i<cur.size();i++)
  108. Answer+=Area(cur[i],P);
  109. return Answer;
  110. }
  111. }Hull;
  112. int n;
  113. int main(){
  114. scanf("%d",&n);
  115. for (int i=1;i<=n;i++){
  116. scanf("%lf%lf%lf",&P[i].x,&P[i].y,&P[i].z);
  117. p[i]=P[i];
  118. }
  119. Hull.Increment(p,n);
  120. printf("%.6lf",Hull.Area(P));
  121. return 0;
  122. }

  

BZOJ1209 [HNOI2004]最佳包裹 三维凸包 计算几何的更多相关文章

  1. bzoj 1209: [HNOI2004]最佳包裹 三维凸包

    1209: [HNOI2004]最佳包裹 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 160  Solved: 58[Submit][Status] ...

  2. bzoj 1964: hull 三维凸包 计算几何

    1964: hull 三维凸包 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 54  Solved: 39[Submit][Status][Discuss ...

  3. 洛谷P2287 [HNOI2004]最佳包裹(三维凸包)

    题面 传送门 题解 左转板子,调个精度就能\(A\)了 //minamoto #include<bits/stdc++.h> #define R register #define fp(i ...

  4. BZOJ1209 最佳包裹 (三维凸包 增量法)

    题意 求三维凸包的表面积. N≤100N\le100N≤100 题解 暴力往当前的凸包里加点.O(n2)O(n^2)O(n2).题解详见大佬博客 扰动函数shakeshakeshake是为了避免四点共 ...

  5. 洛谷P4502 [ZJOI2018]保镖(计算几何+三维凸包)

    题面 传送门 题解 我对计蒜几盒一无所知 顺便\(xzy\)巨巨好强 前置芝士 三维凸包 啥?你不会三维凸包?快去把板子写了->这里 欧拉公式 \[V-E+F=2\] \(V:vertex\)顶 ...

  6. Hnoi2004 金属包裹

    传送门 三维凸包模板题……只是听了听计算几何的课之后心血来潮想写的…… 我的做法很无脑是吧……暴力枚举三个点组成的三角形,然后枚举剩下的点,判断其余点是否都在这个三角形的同一侧,是的话则说明这个三角形 ...

  7. POJ 2225 / ZOJ 1438 / UVA 1438 Asteroids --三维凸包,求多面体重心

    题意: 两个凸多面体,可以任意摆放,最多贴着,问他们重心的最短距离. 解法: 由于给出的是凸多面体,先构出两个三维凸包,再求其重心,求重心仿照求三角形重心的方式,然后再求两个多面体的重心到每个多面体的 ...

  8. hdu4273Rescue(三维凸包重心)

    链接 模板题已不叫题.. 三维凸包+凸包重心+点到平面距离(体积/点积)  体积-->混合积(先点乘再叉乘) #include <iostream> #include<cstd ...

  9. hdu4449Building Design(三维凸包+平面旋转)

    链接 看了几小时也没看懂代码表示的何意..无奈下来问问考研舍友. 还是考研舍友比较靠谱,分分钟解决了我的疑问. 可能三维的东西在纸面上真的不好表示,网上没有形象的题解,只有简单"明了&quo ...

随机推荐

  1. 打包pyinstaller

    安装:pip3 install pyinstaller 了解几个常用命令 参数 用处 -F 将程序打包成一个文件 -w 去除黑框 -i 添加程序图标 我们将需要打包的test.py文件放到桌面上,之后 ...

  2. luogu P4778 Counting swaps

    计数套路题?但是我连套路都不会,,, 拿到这道题我一脸蒙彼,,,感谢@poorpool 大佬的博客的指点 先将第\(i\)位上的数字\(p_i\)向\(i\)连无向边,然后构成了一个有若干环组成的无向 ...

  3. Handler实现与机制 && Blocking Queue && IdleHandler使用

    http://blog.csdn.net/boyupeng/article/details/46685343 IdleHandler处理消息的源码 final Message next() { ... ...

  4. Ubuntu/Debian 8 安装 Intel realsense 摄像头驱动

    ## Make Ubuntu/Debian Up-to-date1. sudo apt-get update && sudo apt-get upgrade && su ...

  5. Tengine HTTPS原理解析、实践与调试【转】

    本文邀请阿里云CDN HTTPS技术专家金九,分享Tengine的一些HTTPS实践经验.内容主要有四个方面:HTTPS趋势.HTTPS基础.HTTPS实践.HTTPS调试. 一.HTTPS趋势 这一 ...

  6. CSS选择器中带点(.)怎么办?

    在SharePoint中很多元素的ID都用点(.)来连接的,比如: <li class="ms-cui-group" id="Ribbon.Documents.Ed ...

  7. C++:vector中的v.at(0)和v[0]的区别

    设v是一个vector的对象, 如果v是非空的,则v.at(0)和v[0]是没有区别的,都是取数组中第一个值: 如果v是空的,则v.at(0)会抛出异常(exception std::out_of_r ...

  8. redis学习笔记(面试题)

    1. 什么是redis Redis是一个数据库,他和我们传统的oracle数据库差别是它是基于内存的数据库:因为是基于内存,所以效率就高,在某些场景下就可以对我们传统的关系型数据库做一个补充 2. r ...

  9. Spring事务回滚和异常类

    1.异常的一些基本知识 异常的架构 异常的继承结构:Throwable为基类,Error和Exception继承Throwable.Error和RuntimeException及其子类成为未检查异常( ...

  10. java模拟form上传数据

    Java模拟form表单上传 查看form表单提交的http请求为 import java.io.*; import java.net.*; public class FileUpload { /** ...