【POJ】【2068】Art Gallery

计算几何/半平面交


  裸的半平面交,关于半平面交的入门请看神犇博客:http://blog.csdn.net/accry/article/details/6070621

  然而代码我是抄的proverbs的……

  大体思路是这样的:(一个增量算法)

    维护一个当前的半平面交的点集,每次用一条直线去cut它:

      依次枚举“凸包”上的点,点在直线左边则保留下来了,否则就丢掉=。=

      同时判一下如果“凸包”上连续的两个点分别在直线两侧,就加入这条“凸包”上的线段与直线的交点= =

    然后新点集get!

  最后求个面积>_>

  有个trick是如果给的顺序是顺时针,需要反转成逆时针(用算多边形面积的方法就可以判断,如果是逆时针,面积为正)

  1 Source Code
  2 Problem: 1279        User: sdfzyhy
  3 Memory: 720K        Time: 32MS
  4 Language: G++        Result: Accepted
  5 
  6     Source Code
  7 
  8     //POJ 1279
  9     #include<cmath>
 10     #include<vector>
 11     #include<cstdio>
 12     #include<cstring>
 13     #include<cstdlib>
 14     #include<iostream>
 15     #include<algorithm>
 16     #define rep(i,n) for(int i=0;i<n;++i)
 17     #define F(i,j,n) for(int i=j;i<=n;++i)
 18     #define D(i,j,n) for(int i=j;i>=n;--i)
 19     #define pb push_back
 20     using namespace std;
 21     inline int getint(){
 22         int v=0,sign=1; char ch=getchar();
 23         while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
 24         while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
 25         return v*sign;
 26     }
 27     const int N=1e5+10;
 28     const double INF=1e9;
 29     typedef long long LL;
 30     /******************tamplate*********************/
 31     const double eps=1e-8;
 32     int dcmp(double x){return x>eps ? 1 : x<-eps ? -1 : 0;}
 33     struct Poi{
 34         double x,y;
 35         Poi(){}
 36         Poi(double x,double y):x(x),y(y){}
 37         void read(){scanf("%lf%lf",&x,&y);}
 38     }p[N],tp[N],s[N],o;
 39     typedef Poi Vec;
 40     Vec operator - (const Poi&a,const Poi &b){return Vec(a.x-b.x,a.y-b.y);}
 41 
 42     int n;
 43     double Cross(const Vec &a,const Vec &b){return a.x*b.y-a.y*b.x;}
 44     double getarea(Poi *p,int n){
 45         double ans=0.0;
 46         F(i,1,n) ans+=Cross(p[i]-o,p[i+1]-o);
 47         return ans*0.5;
 48     }
 49     Poi getpoint(const Poi &a,const Poi &b,const Poi &c,const Poi &d){
 50         Poi ans,tmp=b-a;
 51         double k1=Cross(d-a,c-a),k2=Cross(c-b,d-b);
 52         ans.x=a.x+tmp.x*k1/(k1+k2);
 53         ans.y=a.y+tmp.y*k1/(k1+k2);
 54         return ans;
 55     }
 56 
 57     void init(){
 58         n=getint();
 59         F(i,1,n) p[i].read();
 60         p[n+1]=p[1];
 61     }
 62     void Change(){
 63         F(i,1,n>>1) swap(p[i],p[n-i+1]);
 64         p[n+1]=p[1];
 65     }
 66     void getcut(){
 67         tp[1]=tp[5]=Poi(-INF,-INF);
 68         tp[2]=Poi(INF,-INF);
 69         tp[3]=Poi(INF,INF);
 70         tp[4]=Poi(-INF,INF);
 71         int num=4,size=0;
 72         F(i,1,n){
 73             size=0;
 74             F(j,1,num){
 75                 if (dcmp(Cross(p[i+1]-p[i],tp[j]-p[i]))>=0)
 76                     s[++size]=tp[j];
 77                 if (dcmp(Cross(p[i+1]-p[i],tp[j]-p[i]) * 
 78                          Cross(p[i+1]-p[i],tp[j+1]-p[i]))<0) 
 79                     s[++size]=getpoint(p[i],p[i+1],tp[j],tp[j+1]);
 80             }
 81             s[size+1]=s[1];
 82             F(j,1,size+1) tp[j]=s[j];
 83             num=size;
 84         }
 85         n=num;
 86     }
 87     int main(){
 88     #ifndef ONLINE_JUDGE
 89         freopen("1279.in","r",stdin);
 90         freopen("1279.out","w",stdout);
 91     #endif
 92         int T=getint();
 93         while(T--){
 94             init();
 95             if (dcmp(getarea(p,n))<=0) Change();
 96             getcut();
 97             printf("%.2f\n",fabs(getarea(s,n)));
 98         }
 99         return 0;
100     }
View Code
Art Gallery
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 5805   Accepted: 2455

Description

The art galleries of the new and very futuristic building of the Center for Balkan Cooperation have the form of polygons (not necessarily convex). When a big exhibition is organized, watching over all of the pictures is a big security concern. Your task is that for a given gallery to write a program which finds the surface of the area of the floor, from which each point on the walls of the gallery is visible. On the figure 1. a map of a gallery is given in some co-ordinate system. The area wanted is shaded on the figure 2.

Input

The number of tasks T that your program have to solve will be on the first row of the input file. Input data for each task start with an integer N, 5 <= N <= 1500. Each of the next N rows of the input will contain the co-ordinates of a vertex of the polygon ? two integers that fit in 16-bit integer type, separated by a single space. Following the row with the co-ordinates of the last vertex for the task comes the line with the number of vertices for the next test and so on.

Output

For each test you must write on one line the required surface - a number with exactly two digits after the decimal point (the number should be rounded to the second digit after the decimal point).

Sample Input

1
7
0 0
4 4
4 7
9 7
13 -1
8 -6
4 -4

Sample Output

80.00

Source

[Submit]   [Go Back]   [Status]   [Discuss]

  

posted @ 2015-05-12 11:44  Tunix  阅读(310)  评论(0编辑  收藏  举报