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;
    }
    
    
  • 相关阅读:
    Nginx重写请求后将url?后的参数去除
    Nginx重写请求后将url?后的参数去除
    Nginx重写请求后将url?后的参数去除
    FastReport.Net中使用列表和数组作为报表数据源
    FastReport.Net中使用列表和数组作为报表数据源
    FastReport.Net中使用列表和数组作为报表数据源
    FastReport.Net中使用列表和数组作为报表数据源
    PHP可变参数
    推陈出新:网友解锁 source 命令新的姿势,血的教训!已准备跑路
    分析这家薄利多销的酸菜鱼面,看它的经营之道
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10220288.html
Copyright © 2011-2022 走看看