zoukankan      html  css  js  c++  java
  • POJ 3528Ultimate Weapon解题报告

    直接从别人那复制的代码,惭愧啊,看懂了为自己储存模板。

    View Code
      1 #include<iostream>
      2 #include<cmath>
      3 #include<cstring>
      4 #include<cstdio>
      5 #define N 505
      6 #define eps 0.000001
      7 using namespace std;
      8 struct Point
      9 {
     10     double x,y,z;
     11     Point(){}
     12     Point(double _x,double _y,double _z)
     13     {
     14         x=_x;
     15         y=_y;
     16         z=_z;
     17     }
     18     Point operator-(Point t1)//向量减法
     19     {
     20         return Point(x-t1.x,y-t1.y,z-t1.z);
     21     }
     22     Point operator*(Point t2)//叉积
     23     {
     24         return Point(y*t2.z-t2.y*z,z*t2.x-x*t2.z,x*t2.y-y*t2.x);
     25     }
     26     double operator^(Point t3)//点积
     27     {
     28         return x*t3.x+y*t3.y+z*t3.z;
     29     }
     30 };
     31 struct Plane
     32 {
     33     int a,b,c;//a,b,c为三个点的编号,a,b,c要满足从凸包外面看成右手系
     34     bool in;//表示该平面是否在凸包内
     35 };
     36 void Swap(Point &a,Point &b)
     37 {
     38     Point c;
     39     c=a;
     40     a=b;
     41     b=c;
     42 }
     43 Point point[N];
     44 Plane plane[N*10];
     45 int edge[N][N];
     46 int plen;//计算过的面的个数
     47 void dfs(int p,int t);
     48 double vol(Point p,Plane f)//p与平面abc组成的四面体的有向体积的倍
     49 {
     50     Point a=point[f.a]-p,b=point[f.b]-p,c=point[f.c]-p;
     51     return (a*b)^c;
     52 }
     53 double vlen(Point a)//求向量a的模
     54 {
     55     return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);
     56 }
     57 void deal(int p,int t1,int t2)
     58 {
     59     int t=edge[t1][t2];//搜索与该边相邻的另外一个平面
     60     if(plane[t].in)
     61     {
     62         if(vol(point[p],plane[t])>eps)
     63             dfs(p,t);
     64         else
     65         {
     66             Plane add;
     67             add.a=t2,add.b=t1,add.c=p,add.in=true;//这里注意顺序,就可以不用Swap了,add.a,add.b,add.c要成右手系
     68             edge[add.a][add.b]=edge[add.b][add.c]=edge[add.c][add.a]=plen;
     69             plane[plen++]=add;
     70         }
     71     }
     72 }
     73 void dfs(int p,int t)//递归搜索所有应该从凸包内删除的面
     74 {
     75     plane[t].in=false;
     76     deal(p,plane[t].b,plane[t].a);//注意,a和b的顺序刚好跟下面的相反,为的就是搜索与边(point[plane[t].a],point[plane[t].b])相邻的另外一个平面
     77     deal(p,plane[t].c,plane[t].b);
     78     deal(p,plane[t].a,plane[t].c);
     79 }
     80 int del(int n)//增量法,有n个点,返回计算过的平面个数,若无法构成凸包,则返回-1
     81 {
     82     if(n<4)//如果点数小于,则无法构成凸包,若已保证点数大于或等于,可略去
     83         return -1;
     84 /******************这一段用来保证前四点不共面,若已保证,可略去
     85     bool allTheSamePoint=true;
     86     for(int i=1;i<n;i++)//保证前两点不共点
     87     {
     88         if(vlen(point[i]-point[0])>eps)
     89         {
     90             Swap(point[1],point[i]);
     91             allTheSamePoint=false;
     92             break;
     93         }
     94     }
     95     if(allTheSamePoint)
     96         return -1;
     97     bool allTheSameLine=true;
     98     for(int i=2;i<n;i++)//保证前三点不共线
     99     {
    100         if(vlen((point[1]-point[0])*(point[i]-point[1]))>eps)
    101         {
    102             Swap(point[2],point[i]);
    103             allTheSameLine=false;
    104             break;
    105         }
    106     }
    107     if(allTheSameLine)
    108         return -1;
    109     bool allTheSamePlane=true;
    110     for(int i=3;i<n;i++)//保证前四点不共面
    111     {
    112         if(fabs((point[1]-point[0])*(point[2]-point[0])^(point[i]-point[0]))>eps)
    113         {
    114             Swap(point[3],point[i]);
    115             allTheSamePlane=false;
    116             break;
    117         }
    118     }
    119     if(allTheSamePlane)
    120         return -1;
    121 这一段用来保证前四点不共面,若已保证,可略去************/
    122     plen=0;//计算过的面的个数
    123     Plane add;
    124     for(int i=0;i<4;i++)
    125     {
    126         add.a=(i+1)%4,add.b=(i+2)%4,add.c=(i+3)%4,add.in=true;
    127         if(vol(point[i],add)>0)
    128             swap(add.a,add.b);
    129         edge[add.a][add.b]=edge[add.b][add.c]=edge[add.c][add.a]=plen;//记录与该边相邻的其中一个面,并且该顺序在该面内(从凸包外看)成右手系,因此,该面是唯一的
    130         plane[plen++]=add;
    131     }
    132     for(int i=4;i<n;i++)
    133     {
    134         for(int j=0;j<plen;j++)
    135         {
    136             if(plane[j].in && vol(point[i],plane[j])>eps)
    137             {
    138                 dfs(i,j);
    139                 break;
    140             }
    141         }
    142     }
    143     return plen;
    144 }
    145 double area(Plane a)
    146 {
    147     return vlen((point[a.b]-point[a.a])*(point[a.c]-point[a.a]))/2.0;
    148 }
    149 
    150 int main()
    151 {
    152     int n;
    153     cin>>n;
    154     for(int i=0;i<n;i++)
    155         cin>>point[i].x>>point[i].y>>point[i].z;
    156     int len=del(n);
    157     if(len==-1)
    158         printf("0.000\n");
    159     else
    160     {
    161         double ans=0.0;
    162         for(int i=0;i<len;i++)
    163         {
    164             if(plane[i].in)
    165             {
    166                 ans+=area(plane[i]);
    167             }
    168         }
    169         printf("%.3lf\n",ans);
    170     }
    171 return 0;
    172 }
  • 相关阅读:
    JS高级-虚拟DOM
    JS高级-异步
    tomcat server.xml中文版
    java中的等于
    eclipse version
    angularjs中父,子,兄之间controller值得传递
    《那一天,那一月,那一年,那一世》-------仓央嘉措
    用jsonp格式的数据进行ajax post请求变成get
    git常用指令
    让div支持placeholder属性/模拟输入框的placeholder属性
  • 原文地址:https://www.cnblogs.com/caozhenhai/p/2686112.html
Copyright © 2011-2022 走看看