zoukankan      html  css  js  c++  java
  • UVA12296 Pieces and Discs

    题意

    PDF

    分析

    可以看成直线切割多边形,直接维护。

    对每个多边形考虑每条边和每个点即可。

    时间复杂度?不过(n,m leq 20)这种数据怎么都过了。据说是(O(n^3))的,而且常数也挺小。

    一般的比赛估计不会出这种vector套vector的神题。

    代码

    注意初始化的时候的那个初始长方形的点必须按逆时针顺序来插入。

    我写反了,导致调了一晚上。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<algorithm>
    #include<bitset>
    #include<cassert>
    #include<ctime>
    #include<cstring>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read()
    {
    	rg T data=0;
    	rg int w=1;
    	rg char ch=getchar();
    	while(!isdigit(ch))
    	{
    		if(ch=='-')
    			w=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch))
    	{
    		data=data*10+ch-'0';
    		ch=getchar();
    	}
    	return data*w;
    }
    template<class T>T read(T&x)
    {
    	return x=read<T>();
    }
    using namespace std;
    typedef long long ll;
    
    co double eps=1e-8;
    
    int dcmp(double x)
    {
    	return fabs(x)<eps?0:(x<0?-1:1);
    }
    
    struct Point
    {
    	double x,y;
    	
    	Point(double x=0,double y=0)
    	:x(x),y(y){};
    };
    typedef Point Vector;
    typedef vector<Point> Polygon;
    
    Vector operator+(co Vector&A,co Vector&B)
    {
    	return Vector(A.x+B.x,A.y+B.y);
    }
    
    Vector operator-(co Vector&A,co Vector&B)
    {
    	return Vector(A.x-B.x,A.y-B.y);
    }
    
    Vector operator*(co Vector&A,double p)
    {
    	return Vector(A.x*p,A.y*p);
    }
    
    double Dot(co Vector&A,co Vector&B)
    {
    	return A.x*B.x+A.y*B.y;
    }
    
    double Cross(co Vector&A,co Vector&B)
    {
    	return A.x*B.y-A.y*B.x;
    }
    
    double Length2(co Vector&A)
    {
    	return Dot(A,A);
    }
    
    Point LineLineIntersection(co Point&P,co Vector&v,co Point&Q,co Vector&w)
    {
    	Vector u=P-Q;
    	double t=Cross(w,u)/Cross(v,w);
    	return P+v*t;
    }
    
    bool OnSegment(co Point&p,co Point&a1,co Point&a2)
    {
    	return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;
    }
    
    double PolygonArea(co Polygon&poly)
    {
    	double area=0;
    	int n=poly.size();
    	for(int i=1;i<n-1;++i)
    		area+=Cross(poly[i]-poly[0],poly[(i+1)%n]-poly[0]);
    	return area/2;
    }
    
    Polygon CutPolygon(co Polygon&poly,co Point&A,co Point&B)
    {
    	Polygon newpoly;
    	int n=poly.size();
    	for(int i=0;i<n;++i)
    	{
    		co Point&C=poly[i];
    		co Point&D=poly[(i+1)%n];
    		if(dcmp(Cross(B-A,C-A))>=0)
    			newpoly.push_back(C);
    		if(dcmp(Cross(B-A,C-D))!=0)
    		{
    			Point ip=LineLineIntersection(A,B-A,C,D-C);
    			if(OnSegment(ip,C,D))
    				newpoly.push_back(ip);
    		}
    	}
    	return newpoly;
    }
    
    int PointInPolygon(co Point&p,co Polygon&v)
    {
    	int wn=0;
    	int n=v.size();
    	for(int i=0;i<n;++i)
    	{
    		if(OnSegment(p,v[i],v[(i+1)%n]))
    			return -1;
    		int k=dcmp(Cross(v[(i+1)%n]-v[i],p-v[i]));
    		int d1=dcmp(v[i].y-p.y);
    		int d2=dcmp(v[(i+1)%n].y-p.y);
    		if(k>0&&d1<=0&&d2>0)
    			++wn;
    		if(k<0&&d2<=0&&d1>0)
    			--wn;
    	}
    	if(wn!=0)
    		return 1;
    	return 0;
    }
    
    
    bool InCircle(co Point&p,co Point&center,double R)
    {
    	return dcmp(Length2(p-center)-R*R)<0;
    }
    
    int LineCircleIntersection(co Point&A,co Point&B,co Point&C,double r,double&t1,double&t2)
    {
    	double a=B.x-A.x,
    		   b=A.x-C.x,
    		   c=B.y-A.y,
    		   d=A.y-C.y;
    	
    	double e=a*a+c*c,
    		   f=2*(a*b+c*d),
    		   g=b*b+d*d-r*r,
    		   delta=f*f-4*e*g;
    	if(dcmp(delta)<0)
    		return 0;
    	if(dcmp(delta)==0)
    	{
    		t1=t2=-f/(2*e);
    		return 1;
    	}
    	t1=(-f-sqrt(delta))/(2*e);
    	t2=(-f+sqrt(delta))/(2*e);
    	return 2;
    }
    
    bool CircleIntersectSegment(co Point&A,co Point&B,co Point&p,double R)
    {
    	double t1,t2;
    	int c=LineCircleIntersection(A,B,p,R,t1,t2);
    	if(c<=1)
    		return 0;
    	if(dcmp(t1)>0&&dcmp(t1-1)<0)
    		return 1;
    	if(dcmp(t2)>0&&dcmp(t2-1)<0)
    		return 1;
    	return 0;
    }
    
    vector<Polygon> pieces,new_pieces;
    
    void Cut(int x1,int y1,int x2,int y2)
    {
    	new_pieces.clear();
    	for(int i=0;i<pieces.size();++i)
    	{
    		Polygon left=CutPolygon(pieces[i],Point(x1,y1),Point(x2,y2));
    		Polygon right=CutPolygon(pieces[i],Point(x2,y2),Point(x1,y1));
    		if(left.size()>=3)
    			new_pieces.push_back(left);
    		if(right.size()>=3)
    			new_pieces.push_back(right);
    //		cerr<<"left="<<endl;
    //		for(int j=0;j<left.size();++j)
    //			cerr<<" "<<left[j].x<<","<<left[j].y;
    //		cerr<<endl;
    //		cerr<<"right="<<endl;
    //		for(int j=0;j<right.size();++j)
    //			cerr<<" "<<right[j].x<<","<<right[j].y;
    //		cerr<<endl;
    	}
    	pieces=new_pieces;
    }
    
    bool DiscIntersectPolygon(co Polygon&poly,co Point&p,double R)
    {
    	if(PointInPolygon(p,poly)!=0)
    		return 1;
    	if(InCircle(poly[0],p,R))
    		return 1;
    	int n=poly.size();
    	for(int i=0;i<n;++i)
    	{
    		if(CircleIntersectSegment(poly[i],poly[(i+1)%n],p,R))
    			return 1;
    		if(InCircle((poly[i]+poly[(i+1)%n])*0.5,p,R))
    			return 1;
    	}
    	return 0;
    }
    
    void Query(co Point&p,int R)
    {
    	vector<double>ans;
    	for(int i=0;i<pieces.size();++i)
    		if(DiscIntersectPolygon(pieces[i],p,R))
    			ans.push_back(fabs(PolygonArea(pieces[i])));
    	printf("%d",ans.size());
    	sort(ans.begin(),ans.end());
    	for(int i=0;i<ans.size();++i)
    		printf(" %.2lf",ans[i]);
    	printf("
    ");
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	int n,m,L,W;
    	while(read(n)|read(m)|read(L)|read(W))
    	{
    //		cerr<<"n="<<n<<" m="<<m<<" L="<<L<<" W="<<W<<endl;
    		pieces.clear();
    		
    		Polygon bbox;
    		bbox.push_back(Point(0,0)); // edit 1:must follow the order
    		bbox.push_back(Point(L,0));
    		bbox.push_back(Point(L,W));
    		bbox.push_back(Point(0,W));
    		pieces.push_back(bbox);
    		
    		for(int i=0;i<n;++i)
    		{
    			int x1,y1,x2,y2;
    			read(x1),read(y1),read(x2),read(y2);
    //			cerr<<"x1="<<x1<<" y1="<<y1<<" x2="<<x2<<" y2="<<y2<<endl;
    			Cut(x1,y1,x2,y2);		
    //			for(int i=0;i<pieces.size();++i)
    //			{
    //				cerr<<i<<" poly="<<endl;
    //				for(int j=0;j<pieces[i].size();++j)
    //					cerr<<" "<<pieces[i][j].x<<","<<pieces[i][j].y;
    //				cerr<<endl;
    //			}
    		}
    		
    		for(int i=0;i<m;++i)
    		{
    			int x,y,R;
    			read(x),read(y),read(R);
    			Query(Point(x,y),R);
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    单点登录学习的教程
    单点登录
    Linux下VI的使用
    伪分布式下的hadoop简单配置
    Linux下配置Java环境变量
    spring mvc 重新定向到一个新的Url
    LeetCode --- 字符串系列 ---“气球” 的最大数量
    http 简述
    dpr 与 移动端 1px 问题
    rem 与 vm 布局
  • 原文地址:https://www.cnblogs.com/autoint/p/10182376.html
Copyright © 2011-2022 走看看