裸的半平面交,关于半平面交的入门请看神犇博客: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

相关文章: