zoukankan      html  css  js  c++  java
  • BZOJ 1043 [HAOI2008]下落的圆盘 ——计算几何

    腊鸡题目。

    我们考虑倒着加入圆盘,考虑每一个圆被之后覆盖的弧的总长度。

    首先需要把包含的情况去掉。

    然后用解析几何算出相交的弧的位置。

    然后求一个交。

    然后把剩下的结果加入答案中。

    写了一下午,发现cos值可能大于1,不能用acos函数计算。

    QAQ

    #include <map>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define eps 1e-8
    #define sqr(x) x*x
    #define ll long long
    #define mp make_pair
    
    const double pi=acos(-1.0);
    
    struct Vector{
    	double x,y;
    	void print()
    	{
    		printf("Vector -> (%.3f,%.3f)
    ",x,y);
    	}
    };
    
    struct Point{
    	double x,y;
    	void print()
    	{
    		printf("Point . (%.3f,%.3f)
    ",x,y);
    	}
    };
    
    Vector operator + (Vector a,Vector b)
    {Vector ret;ret.x=a.x+b.x;ret.y=a.y+b.y;return ret;}
    
    Vector operator - (Vector a,Vector b)
    {Vector ret;ret.x=a.x-b.x;ret.y=a.y-b.y;return ret;}
    
    Point operator + (Point a,Vector b)
    {Point ret;ret.x=a.x+b.x;ret.y=a.y+b.y;return ret;}
    
    Vector operator - (Point a,Point b)
    {Vector ret;ret.x=a.x-b.x;ret.y=a.y-b.y;return ret;}
    
    Vector operator * (Vector a,double b)
    {Vector ret;ret.x=a.x*b;ret.y=a.y*b;return ret;}
    
    double operator * (Vector a,Vector b)
    {return a.x*b.y-a.y*b.x;}
    
    Vector Turn(Vector a,double b)
    {
    	Vector ret;
    	ret.x=a.x*cos(b)-a.y*sin(b);
    	ret.y=a.x*sin(b)+a.y*cos(b);
    	return ret;
    }
    
    int n;
    
    struct Circle{
    	double x,y,r;
    	void print()
    	{
    		printf("Circle (%.3f,%.3f) r = %.3f
    ",x,y,r);
    	}
    }a[1005];
    
    double dst(double x1,double y1,double x2,double y2)
    {return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));}
    
    int dcmp(double x)
    {
    	if (x>eps) return 1;
    	if (fabs(x)<eps) return 0;
    	return -1;
    }
    
    bool in(Circle a,Circle b)
    {
    	if (dcmp(dst(a.x,a.y,b.x,b.y)-(b.r-a.r))<=0) return true;
    	return false;
    }
    
    struct Cut_Cir{
    	double l,r;
    	void print()
    	{
    		printf("Ang (%.3f,%.3f)
    ",l,r);
    	}
    }sta[1000005];
    int top=0;
    
    double nege(double x)
    {
    	if (dcmp(x)==-1) x+=2*pi;
    	while (dcmp(x-2*pi)>=0) x-=2*pi;
    	return x;
    }
    
    void Cut(int pos)
    {
    	top=0; double dist; Vector v0,v1,v2;
    	F(i,pos+1,n)
    		if ((dist=dst(a[pos].x,a[pos].y,a[i].x,a[i].y))<a[pos].r+a[i].r)
    		{
    			double ang; ang=(sqr(a[pos].r)+sqr(dist)-sqr(a[i].r))/(2*a[pos].r*dist);
    			if (ang>1.0) continue;
    			ang=acos(ang);
    			v0.x=a[i].x-a[pos].x;v0.y=a[i].y-a[pos].y;
    			v0=v0*(1.0/sqrt(sqr(v0.x)+sqr(v0.y))*a[pos].r);
    			v1=Turn(v0,ang);
    			v2=Turn(v0,-ang);
    			double t1=atan2(v1.y,v1.x),t2=atan2(v2.y,v2.x);
    			t1+=pi;t2+=pi;
    			while (t1>2*pi) t1-=2*pi;
    			while (t2>2*pi) t2-=2*pi;
    			if (t1<t2)
    			{
    				++top;
    				sta[top].l=0;
    				sta[top].r=t1;
    				++top;
    				sta[top].l=t2;
    				sta[top].r=2*pi;
    			}
    			else
    			{
    				++top;
    				sta[top].l=t2;
    				sta[top].r=t1;
    			}
    		}
    }
    
    double C(Circle a)
    {return a.r*2*pi;}
    
    bool cmp2(Cut_Cir a,Cut_Cir b)
    {return a.l<b.l;}
    
    double cal(double r)
    {
    	sort(sta+1,sta+top+1,cmp2);
    	double now=0,ret=0;
    	F(i,1,top)
    	{
    		now=max(now,sta[i].l);
    		ret+=max(0.0,sta[i].r-now);
    		now=max(now,sta[i].r);
    	}
    	return ret*r;
    }
    
    double ans=0;
    
    int main()
    {
    	scanf("%d",&n);
    	F(i,1,n) scanf("%lf%lf%lf",&a[i].r,&a[i].x,&a[i].y);
    	F(i,1,n)
    	{
    		int flag=1;
    		F(j,i+1,n) if (in(a[i],a[j]))
    			flag=0;
    		if (!flag) continue;
    		Cut(i);
    		ans+=C(a[i]);
    		ans-=cal(a[i].r);
    	}
    	printf("%.3f
    ",ans);
    }
    

      

  • 相关阅读:
    Microsoft.Office.Interop.Excel 组件的报错检索 COM 类工厂中 CLSID,错误码:80070005
    SQLServer编写自己的切分函数 SPLIT和带排序的切割函数 SPLITSort
    Powerdesigner 导出Excel格式数据字典 导出Excel格式文件
    NPOI 导入导出excel两种方式 和 错误 无法访问已关闭的流解决方式
    unable to start the virtual device;Genymotion启动安卓模拟器出错
    datetimepicker 时间控件 1899年问题以及解决方法
    Linux命令大全
    Linux工具包
    Redis
    MySQL索引
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6674363.html
Copyright © 2011-2022 走看看