求的是凸包有多少个面。

注意,求的是面。这就需要把同一个面的三角形合并。只需判断两个三角形的法向量是否同向平行。

  1. /*
  2. 增量法求凸包。选取一个四面体,同时把它各面的方向向量向外,增加一个点时,若该点与凸包上的某些面的方
  3. 向向量在同一侧,则去掉那些面,并使某些边与新增点一起连成新的凸包上的面。
  4. */
  5.  
  6. #include <iostream>
  7. #include <cstring>
  8. #include <cstdio>
  9. #include <algorithm>
  10. #include <cmath>
  11.  
  12. using namespace std;
  13. const int MAXN=350;
  14. const double eps=1e-8;
  15. struct point {
  16. double x,y,z;
  17. };
  18. struct face {
  19. int a,b,c;
  20. bool ok;
  21. };
  22. int n; //初始点数
  23. point p[MAXN]; //空间点
  24. int trianglecnt; //凸包上三角形数
  25. face tri[6*MAXN]; //凸包上被创建的三角形
  26. int vis[MAXN][MAXN]; //点i到点j是属于哪一个三角形。此处是有方向
  27. bool vit[MAXN*6];
  28.  
  29. point operator -(const point &x, const point &y){
  30. point ret;
  31. ret.x=x.x-y.x; ret.y=x.y-y.y; ret.z=x.z-y.z;
  32. return ret;
  33. }
  34.  
  35. point operator * (const point &u,const point &v){ //叉积
  36. point ret;
  37. ret.x=u.y*v.z-u.z*v.y;
  38. ret.y=u.z*v.x-u.x*v.z;
  39. ret.z=u.x*v.y-u.y*v.x;
  40. return ret;
  41. }
  42.  
  43. double operator ^(const point &u,const point &v){
  44. return (u.x*v.x+u.y*v.y+u.z*v.z);
  45. }
  46.  
  47. double dist(point t){
  48. return sqrt(t.x*t.x+t.y*t.y+t.z*t.z);
  49. }
  50.  
  51. double ptoplane(point &tmp,face &f){ //若结果大于0,证明点面的同向,即法向量方向
  52. point m=p[f.b]-p[f.a]; point n=p[f.c]-p[f.a];
  53. point t=tmp-p[f.a];
  54. return (m*n)^t;
  55. }
  56.  
  57. double farea(point a,point b,point c ){
  58. point t1=a-c; point t2=b-c;
  59. return fabs(dist(t1*t2));
  60. }
  61. void dfs(int pt, int ct);
  62. void deal(int pt,int a,int b){
  63. int f=vis[a][b]; //所属三角形,即原来的ab。
  64. face add;
  65. if(tri[f].ok){
  66. if((ptoplane(p[pt],tri[f]))>eps) dfs(pt,f); //若点同样在该f三角形方向一侧,继续调整
  67. else {
  68. add.a=b; add.b=a; add.c=pt; add.ok=1;
  69. vis[pt][b]=vis[a][pt]=vis[b][a]=trianglecnt;
  70. tri[trianglecnt++]=add;
  71. }
  72. }
  73. }
  74.  
  75. void dfs(int pt, int ct){
  76. tri[ct].ok=0; //去掉该面
  77. deal(pt,tri[ct].b,tri[ct].a); //因为有向边ab所属三角形去掉,则反方向边必定属于另一个三角形.
  78. deal(pt,tri[ct].c,tri[ct].b);
  79. deal(pt,tri[ct].a,tri[ct].c);
  80. }
  81.  
  82. void construct (){
  83. int i,j;
  84. trianglecnt=0;
  85. if(n<4) return ; //不可能构成一个多面体
  86. bool tmp=true;
  87. for(i=1;i<n;i++){ //不共点两点
  88. if(dist(p[0]-p[i])>eps){
  89. swap(p[1],p[i]); tmp=false; break;
  90. }
  91. }
  92. if(tmp) return ;
  93. tmp=true;
  94. for(i=2;i<n;i++){ //不共线
  95. if(dist((p[0]-p[1])*(p[1]-p[i]))>eps){
  96. swap(p[2],p[i]); tmp=false; break;
  97. }
  98. }
  99. if(tmp) return ;
  100. tmp=true;
  101. for(i=3;i<n;i++){ //四点不共面K
  102. if(fabs((p[0]-p[1])*(p[1]-p[2])^(p[0]-p[i]))>eps){
  103. swap(p[3],p[i]); tmp=false; break;
  104. }
  105. }
  106. if(tmp) return ;
  107. face add;
  108. for(i=0;i<4;i++){ //使各三角形的方向向量向外,同时记录下三角形的序号
  109. add.a=(i+1)%4; add.b=(i+2)%4; add.c=(i+3)%4; add.ok=1; //等于1表示在凸包上
  110. if(ptoplane(p[i],add)>0) swap(add.b,add.c);
  111. vis[add.a][add.b]=vis[add.b][add.c]=vis[add.c][add.a]=trianglecnt;
  112. tri[trianglecnt++]=add;
  113. }
  114. for(i=4;i<n;i++){ //构建凸包
  115. for(j=0;j<trianglecnt;j++){
  116. if(tri[j].ok&&(ptoplane(p[i],tri[j]))>eps){ //增加点可见该平,即在面方向一侧
  117. dfs(i,j); break;
  118. }
  119. }
  120. }
  121. int cnt=trianglecnt;
  122. trianglecnt=0;
  123. for(i=0;i<cnt;i++){ //只有ok为1的才属于凸包上的三角形
  124. if(tri[i].ok){
  125. tri[trianglecnt++]=tri[i];
  126. }
  127. }
  128. }
  129.  
  130. void clean(){
  131. memset(vit,false,sizeof(vit));
  132. int counted=0;
  133. for(int i=0;i<trianglecnt;i++){
  134. if(vit[i]) continue;
  135. vit[i]=true;
  136. point vect1=(p[tri[i].b]-p[tri[i].a])*(p[tri[i].c]-p[tri[i].a]);
  137. counted++;
  138. for(int j=i+1;j<trianglecnt;j++){
  139. point vect2=(p[tri[j].b]-p[tri[j].a])*(p[tri[j].c]-p[tri[j].a]);
  140. if(dist(vect1*vect2)<eps&&(vect1^vect2)>0)
  141. vit[j]=true;
  142. }
  143. }
  144. printf("%d\n",counted);
  145. }
  146.  
  147. int main(){
  148. while(scanf("%d",&n)!=EOF){
  149. memset(vis,-1,sizeof(vis));
  150. for(int i=0;i<n;i++)
  151. scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
  152. construct();
  153. clean();
  154. }
  155. }

  

HDU 3662的更多相关文章

  1. 【HDU 3662】3D Convex Hull

    http://acm.hdu.edu.cn/showproblem.php?pid=3662 求给定空间中的点的三维凸包上有多少个面. 用增量法,不断加入点,把新加的点能看到的面都删掉,不能看到的面与 ...

  2. hdu 3662 3D Convex Hull

    Problem - 3662 题意很简单,构造三维凸包,求凸包有多少个面. 代码如下: #include <cstdio> #include <iostream> #inclu ...

  3. hdu 1284 钱币兑换问题 完全背包

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1284 递推公式:dp[i] = sum(dp[i], dp[i-C]) /* 钱币兑换问题 Time ...

  4. 【转载】图论 500题——主要为hdu/poj/zoj

    转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并 ...

  5. HDU 5643 King's Game 打表

    King's Game 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5643 Description In order to remember hi ...

  6. hdu图论题目分类

    =============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many ...

  7. poj和hdu部分基础算法分类及难度排序

    最近想从头开始刷点基础些的题,正好有个网站有关于各大oj的题目分类(http://www.pythontip.com/acm/problemCategory),所以写了点脚本把hdu和poj的一些题目 ...

  8. HDU图论题单

    =============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many ...

  9. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

随机推荐

  1. 洛谷 P3515 [ POI 2011 ] Lightning Conductor —— 决策单调性DP

    题目:https://www.luogu.org/problemnew/show/P3515 决策单调性... 参考TJ:https://www.cnblogs.com/CQzhangyu/p/725 ...

  2. Too-Java:Intellij Idea

    ylbtech-Too-Java:Intellij Idea IDEA 全称 IntelliJ IDEA,是java编程语言开发的集成环境.IntelliJ在业界被公认为最好的java开发工具之一,尤 ...

  3. express4里要单独安装cookie-parser和express-session

    express4里要单独安装cookie-parser和express-session express4里要单独安装cookie-parser和express-session: 1 2 npm ins ...

  4. Java压缩技术(二) ZIP压缩——Java原生实现

    原文:http://snowolf.iteye.com/blog/642298 去年整理了一篇ZLib算法Java实现(Java压缩技术(一) ZLib),一直惦记却没时间补充.今天得空,整理一下ZI ...

  5. (三)Appium-desktop 打包

    appium-desktop经过二次开发后,需要打包为应用提供给其它同学使用.我们知道appium-desktop是使用electron来构建跨平台桌面应用程序.electron有electron-p ...

  6. Spring Boot (19) servlet、filter、listener

    servlet.filter.listener,在spring boot中配置方式有两种:一种是以servlet3开始提供的注解方式,另一种是spring的注入方式. servlet注解方式 serv ...

  7. Spring Boot (5) Spring Boot配置详解

    application.properties application.properties是spring boot默认的配置文件,spring boot默认会在以下两个路径搜索并加载这个文件 src\ ...

  8. jQueryAjax模拟按键消抖(可设置抖动延迟时间)

    在硬件中,按键等都会有抖动现象,如何消除抖动,不重复触发事件呢,这就要用到消抖机制了. 这是我用jQuery模拟硬件消抖原理,额,可能是吧...又不对的地方,希望有高手指点指点. <!DOCTY ...

  9. webstorm for mac

    mac上使用webstrom,破解的方法 参见博客:Webstorm 破解2016.1 for mac 上面的说明有点问题,博主的写的有点问题.应该是1.先打开到注册页面:2.再关闭webstrom; ...

  10. 团体程序设计天梯赛-练习集-L1-042. 日期格式化

    L1-042. 日期格式化 世界上不同国家有不同的写日期的习惯.比如美国人习惯写成“月-日-年”,而中国人习惯写成“年-月-日”.下面请你写个程序,自动把读入的美国格式的日期改写成中国习惯的日期. 输 ...