zoukankan      html  css  js  c++  java
  • 【BZOJ】2178: 圆的面积并

    http://www.lydsy.com/JudgeOnline/problem.php?id=2178

    题意:给出n<=1000个圆,求这些圆的面积并


    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    #include <sstream>
    using namespace std;
    typedef long long ll;
    #define pb push_back
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define error(x) (!(x)?puts("error"):0)
    #define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
    inline int getint() { static int r, k; r=0,k=1; static char c; c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    
    const double eps=1e-6, PI=acos(-1);
    int dcmp(double x) { return abs(x)<eps?0:(x<0?-1:1); }
    double sqr(double x) { return x*x; }
    struct iP { double x, y; iP(double _x=0, double _y=0) : x(_x), y(_y) {} };
    double dis(iP &a, iP &b) { return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); }
    struct iC {
    	iP p; double r;
    	iP getP(double d) { return iP(p.x+cos(d)*r, p.y+sin(d)*r); }
    	double areaH(double d) { return (d-sin(d))/2*sqr(r); }
    };
    double angle(iP &a, iP &b) {
    	static double x, y;
    	x=b.x-a.x; y=b.y-a.y;
    	return atan2(y, x);
    }
    void CCi(iC &a, iC &b, double &ang1, double &ang2) {
    	static double ang, d, R, r, da;
    	d=dis(a.p, b.p); //dbg(d);
    	ang=angle(a.p, b.p);
    	R=a.r; r=b.r; //dbg((sqr(R)+sqr(d)-sqr(r))/2/R/d);
    	da=acos((sqr(R)+sqr(d)-sqr(r))/2/R/d);
    	ang1=ang-da;
    	ang2=ang+da;
    }
    
    const int N=1105;
    iC a[N];
    int n, cnt;
    bool nok[N];
    struct dat { double pos; int k; }b[N*5];
    bool cmp(const dat &a, const dat &b) { return a.pos<b.pos; }
    
    int main() {
    	read(n);
    	for1(i, 1, n) scanf("%lf%lf%lf", &a[i].p.x, &a[i].p.y, &a[i].r);
    	for1(i, 1, n) for1(j, 1, n) if(!nok[j] && i!=j) {
    		double d=dis(a[i].p, a[j].p);
    		if(dcmp(a[j].r-a[i].r-d)>=0) { nok[i]=1; break; }
    	}
    	double ang1, ang2, PI2=PI*2, ans=0;
    	int sum=0;
    	iP A, B;
    	for1(i, 1, n) if(!nok[i]) {
    		cnt=0;
    		for1(j, 1, n) if(i!=j && !nok[j]) {
    			if(dcmp(dis(a[i].p, a[j].p)-a[i].r-a[j].r)>=0) continue;
    			CCi(a[i], a[j], ang1, ang2);
    			if(dcmp(ang1)<0) ang1+=PI2;
    			if(dcmp(ang2)<0) ang2+=PI2;
    			if(dcmp(ang1-ang2)>0) {
    				++cnt; b[cnt].pos=0; b[cnt].k=1;
    				++cnt; b[cnt].pos=ang2; b[cnt].k=-1;
    				++cnt; b[cnt].pos=ang1; b[cnt].k=1;
    				++cnt; b[cnt].pos=PI2; b[cnt].k=-1;
    			}
    			else {
    				++cnt; b[cnt].pos=ang1; b[cnt].k=1;
    				++cnt; b[cnt].pos=ang2; b[cnt].k=-1;
    			}
    		}
    		++cnt; b[cnt].pos=0; b[cnt].k=0;
    		++cnt; b[cnt].pos=PI2; b[cnt].k=0;
    		sort(b+1, b+1+cnt, cmp);
    		sum=0;
    		for1(j, 1, cnt-1) {
    			sum+=b[j].k;
    			if(!sum) {
    				ans+=a[i].areaH(b[j+1].pos-b[j].pos);
    				A=a[i].getP(b[j].pos);
    				B=a[i].getP(b[j+1].pos);
    				ans+=(A.x*B.y-A.y*B.x)/2;
    			}
    		}
    	}
    	printf("%.3f
    ", ans);
    	return 0;
    }
    

    这题坑了我3h啊啊啊啊啊.....................................................我就一sb...

    这题有多种解法,什么是辛普森积分我不知道QAQ因此这种做法是一个坑....以后再填..

    首先得知道如何求这些圆的并:

    圆的面积并=每个圆没有被覆盖的弧(弦那里算起)的面积和+所有相交圆被覆盖弧所组成的多边形(由弦做边)

    正确性自己画图.....

    因此题目变为先求没有被覆盖的弧(直接离散圆周长为线,具体操作请看上上一题...),然后算出每个圆未被覆盖(就是覆盖弧的弦以外的)的面积,然后再用叉积求出多边形面积(原理就是多边形的面积可以通过加加减减得到...)

    然后就完了

    好题!

  • 相关阅读:
    反射(8)程序集反射 Type 类
    反射(5)CLR 运行时探测程序集引用的步骤
    反射(1)程序集基础知识
    csc.exe(C# 编译器)
    证书(1)数字签名基础知识
    反射(7)动态程序集加载Load方法
    SignTool.exe(签名工具)
    反射(3)程序集加载 Assembly类
    关于卡巴斯基安全免疫区随笔
    文本提取工具 TextHelper
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4203875.html
Copyright © 2011-2022 走看看