zoukankan      html  css  js  c++  java
  • 【CQOI2006】凸多边形

    1713 -- 【CQOI2006】凸多边形

    Description

      逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:
            img
      则相交部分的面积为5.233。

    Input

      第一行有一个整数n,表示凸多边形的个数
      以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。

    Output

      输出仅包含一个实数,表示相交部分的面积,保留三位小数。

    Sample Input

    2
    6
    -2 0
    -1 -2
    1 -2
    2 0
    1 2
    -1 2
    4
    0 -3
    1 -1
    2 2
    -1 0

    Sample Output

    5.233

    (\)

    半平面交的模板。

    (atan2)求的是奇角(值域是((-pi,pi]))。

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define N 200005
    #define eps 1e-12
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    struct Point {
    	double x,y;
    	double angle() {return atan2(y,x);}
    	void out() {cout<<"("<<x<<","<<y<<") ";}
    };
    typedef Point Vector;
    Point operator + (const Point &a,const Point &b) {return (Point) {a.x+b.x,a.y+b.y};}
    Point operator - (const Point &a,const Point &b) {return (Point) {a.x-b.x,a.y-b.y};}
    Point operator * (const Point &a,double b) {return (Point) {a.x*b,a.y*b};}
    Point operator / (const Point &a,double b) {return (Point) {a.x/b,a.y/b};}
    
    double Cross(const Vector &a,const Vector &b) {return a.x*b.y-a.y*b.x;}
    
    struct Line {
    	Point s,t;
    	double ang;
    	void Init(Point a,Point b) {
    		s=a,t=b;
    		ang=(t-s).angle();
    	}
    	void out() {s.out(),t.out();cout<<ang;puts("");}
    }l[N<<1];
    
    int tot;
    bool OnRight(const Line &a,const Point &b) {return Cross(a.t-a.s,b-a.s)<-eps;}
    bool operator <(const Line &a,const Line &b) {
    	double x=a.ang-b.ang;
    	if(fabs(x)>eps) return x<0;
    	return OnRight(a,b.t);
    }
    
    Point intersection(const Line &a,const Line &b) {
    	double S=Cross(a.t-a.s,b.s-a.s),T=Cross(a.t-a.s,b.t-a.s);
    	return b.s+(b.t-b.s)*(S/(S-T));
    }
    bool is_parallel(const Line &a,const Line &b) {
    	return fabs(Cross(a.t-a.s,b.t-b.s))<eps;
    }
    
    int n,m;
    Point p[N];
    bool SI(Line *l,int n,int &m) {
    	static Line q[N];
    	static Point q2[N];
    	int h=0,t=0;
    	q[h=t=1]=l[1];
    	for(int i=2;i<=n;i++) {
    		if(fabs(l[i].ang-l[i-1].ang)<eps) continue ;
    		if(h<t&&(is_parallel(q[h],q[h+1])||is_parallel(q[t],q[t-1]))) {
    			return 0;
    		}
    		while(h<t&&OnRight(l[i],q2[t-1])) t--;
    		while(h<t&&OnRight(l[i],q2[h])) h++;
    		q[++t]=l[i];
    		if(h<t) q2[t-1]=intersection(q[t],q[t-1]);
    	}
    	while(h<t&&OnRight(q[h],q2[t-1])) t--;
    	while(h<t&&OnRight(q[t],q2[h])) h++;
    	if(t-h<=1) return 0;
    	q2[t]=intersection(q[h],q[t]);
    	m=t-h+1;
    	for(int i=1;i<=m;i++) p[i]=q2[i+h-1];
    	return 1;
    }
    
    double area(Point *p,int n) {
    	double ans=0;
    	for(int i=2;i<n;i++) {
    		ans+=Cross(p[i]-p[1],p[i+1]-p[1]);
    	}
    	return ans/2.0;
    }
    
    int main() {
    	int T=Get(); 
    	while(T--) {
    		n=Get();
    		for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
    		p[n+1]=p[1];
    		for(int i=1;i<=n;i++) l[++tot].Init(p[i],p[i+1]);
    	}
    	sort(l+1,l+1+tot);
    	if(SI(l,tot,n)) {
    		cout<<fixed<<setprecision(3)<<area(p,n);
    	} else cout<<"0.000";
    	return 0;
    }
    
    
  • 相关阅读:
    ADB命令大全
    Backup your Android without root or custom recovery -- adb backup
    Content portal for Pocketables Tasker articles
    Is there a way to detect if call is in progress? Phone Event
    Tasker to proximity screen off
    Tasker to detect application running in background
    Tasker to create toggle widget for ES ftp service -- Send Intent
    Tasker to proximity screen on
    Tasker to answer incoming call by pressing power button
    Tasker to stop Poweramp control for the headset while there is an incoming SMS
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10220288.html
Copyright © 2011-2022 走看看