zoukankan      html  css  js  c++  java
  • bzoj2618 [Cqoi2006]凸多边形

    [Cqoi2006]凸多边形

    Time Limit: 5 Sec Memory Limit: 128 MB

    Description

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

    则相交部分的面积为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

    HINT

    100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数

    我会半平面交啦啦啦~~~

    半平面交我不用多说,有篇论文写的太好啦! Orz

    https://wenku.baidu.com/view/c750720bf78a6529647d53ae.html
    (顺面可以学一波外语~嘿嘿嘿~)

    我就精心画几张图来表示一下啦~~~

    
    #include<bits/stdc++.h>
    using namespace std;
    struct vec{
    	double x, y;
    	vec() {}
    	vec(double a, double b) { x = a, y = b; }
    	vec operator - (const vec &A){ return vec(x - A.x, y - A.y); }
    };
    struct Line{
    	vec A, B; double polar;
    	bool operator < (const Line &A)const{ return polar < A.polar; }
    }linL, lpl[505], lpd[505];
    const int eps = 1e-8;
    vector<Line> L;
    vector<vec> ans;
    int n, m, l, r;
    
    double cross(vec A, vec B){ return A.x * B.y - A.y * B.x; }
    bool onleft(vec A, Line X){ return cross(X.B - X.A, A - X.A) > 0; }
    
    vec inter(Line A, Line B){
    	double s1, s2, k; vec ret;
    	s1 = cross((A.B - A.A), (B.B - A.A));
    	s2 = cross((B.A - A.A), (A.B - A.A));
    	k = s2 / (s1 + s2);
    	ret.x = B.A.x + k * (B.B.x - B.A.x); ret.y = B.A.y + k * (B.B.y - B.A.y);
    	return ret;
    }
    
    inline void putit()
    {
    	int mx; vec p[55]; scanf("%d", &n);
    	for(int i = 1; i <= n; ++i){
    		scanf("%d", &mx);
    		for(int j = 1; j <= mx; ++j) scanf("%lf%lf", &p[j].x, &p[j].y);
    		for(int j = 1; j < mx; ++j){
    			linL.A = p[j], linL.B = p[j + 1]; 
    			linL.polar = atan2(linL.B.x - linL.A.x, linL.B.y - linL.A.y);
    			L.push_back(linL);
    		}
    			linL.A = p[mx], linL.B = p[1]; 
    			linL.polar = atan2(linL.B.x - linL.A.x, linL.B.y - linL.A.y);
    			L.push_back(linL);		
    	}
    }
    
    inline void HPI()
    {
    	sort(L.begin(), L.end());
    	int len = L.size() - 1; 
    	int siz = 1; lpd[1] = L[0];
    	for(int i = 1; i <= len; ++i){
    		if(L[i].polar != lpd[siz].polar) { lpd[++siz] = L[i]; continue; }
    		if(onleft(L[i].A, lpd[siz])) lpd[siz] = L[i];
    	}
    	l = 1; r = 2; lpl[1] = lpd[1], lpl[2] = lpd[2];
    	for(int i = 3; i <= siz; ++i){
    		while(l < r && !onleft(inter(lpl[r], lpl[r - 1]), lpd[i])) r--;
    		while(l < r && !onleft(inter(lpl[l], lpl[l + 1]), lpd[i])) l++;
    		lpl[++r] = lpd[i];
    	}
    	while(l < r && !onleft(inter(lpl[r], lpl[r - 1]), lpl[l])) r--;
    	while(l < r && !onleft(inter(lpl[l], lpl[l + 1]), lpl[r])) l++;
    }
    
    inline void print()
    {
    	lpl[r + 1] = lpl[l];
    	for(int i = l; i <= r; ++i) ans.push_back(inter(lpl[i], lpl[i + 1]));
    	if(ans.size() < 3) {printf("0.000"); return;}
    	double ret = 0; 	
    	ans.push_back(ans[0]);
    	int len = ans.size() - 1;
    	for(int i = 0; i < len; ++i) 
    	ret += cross(ans[i], ans[i + 1]);
    	printf("%.3lf", fabs(ret) / 2);
    }
    
    int main()
    {
    	putit();
    	HPI();
    	print();
    	return 0;
    }
    
    
    心如花木,向阳而生。
  • 相关阅读:
    Network (poj1144)
    C. Hongcow Builds A Nation
    ZYB loves Xor I(hud5269)
    D. Chloe and pleasant prizes
    Game(hdu5218)
    约瑟夫环的递推方法
    Misaki's Kiss again(hdu5175)
    Exploration(hdu5222)
    B. Arpa's weak amphitheater and Mehrdad's valuable Hoses
    C. Arpa's loud Owf and Mehrdad's evil plan
  • 原文地址:https://www.cnblogs.com/LLppdd/p/8837176.html
Copyright © 2011-2022 走看看