• CF 698 F 题解


    这题计算几何,非常毒瘤,思路比较简单,但是会有非常毒瘤的数据卡精度。我写了300行,还特判调整了(eps).
    代码:

    /*
    {
    ######################
    #       Author       #
    #        Gary        #
    #        2020        #
    ######################
    */
    #include<bits/stdc++.h>
    #define rb(a,b,c) for(int a=b;a<=c;++a)
    #define rl(a,b,c) for(int a=b;a>=c;--a)
    #define LL long long
    #define IT iterator
    #define PB push_back
    #define II(a,b) make_pair(a,b)
    #define FIR first
    #define SEC second
    #define FREO freopen("check.out","w",stdout)
    #define rep(a,b) for(int a=0;a<b;++a)
    #define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
    #define random(a) rng()%a
    #define ALL(a) a.begin(),a.end()
    #define POB pop_back
    #define ff fflush(stdout)
    #define fastio ios::sync_with_stdio(false)
    #define check_min(a,b) a=min(a,b)
    #define check_max(a,b) a=max(a,b)
    using namespace std;
    //inline int read(){
    //    int x=0;
    //    char ch=getchar();
    //    while(ch<'0'||ch>'9'){
    //        ch=getchar();
    //    }
    //    while(ch>='0'&&ch<='9'){
    //        x=(x<<1)+(x<<3)+(ch^48);
    //        ch=getchar();
    //    }
    //    return x;
    //}
    const int INF=0x3f3f3f3f;
    typedef pair<int,int> mp;
    /*}
    */
    typedef long double lb;
    lb eps =1e-6;
    struct point{
    	lb x,y;
    	point (){
    		x=y=0;
    	}
    	point (lb X,lb Y){
    		x=X,y=Y;
    	}
    	bool operator < (point oth){
    		if(abs(x-oth.x)<=eps) {
    			if(abs(y-oth.y)<=eps) return 0;
    			return y<oth.y;	
    		}
    		return x<oth.x;
    	}
    	bool operator == (point oth){
    		return abs(x-oth.x)<=eps&&abs(y-oth.y)<=eps;
    	}
    	bool operator <=(point oth){
    		return point (x,y)<oth||point(x,y)==oth;
    	}
    };
    struct line{
    	lb s,t,k,b;
    	line (){
    		s=t=k=b=0;
    	}
    	line (point A,point B){
    		if(A.x>B.x) swap(A,B);
    		s=A.x;
    		t=B.x;
    		if(abs(A.x-B.x)<=eps){
    			s=A.y;
    			t=B.y;
    			if(s>t) swap(s,t);
    			b=A.x;
    			k=1e18;
    		}
    		else{
    			k=(B.y-A.y)/(B.x-A.x);
    			b=A.y-k*A.x;
    		}
    	}
    	bool in(point oth){
    		if(k==1e18){
    			return oth.y+eps>=s&&oth.y-eps<=t;
    		}
    		return oth.x+eps>=s&&oth.x-eps<=t;
    	}
    	bool strictin(point oth){
    		if(k==1e18){
    			return oth.y-eps>s&&oth.y+eps<t;
    		}
    		return oth.x-eps>s&&oth.x+eps<t;
    	}
    	bool operator == (line oth){
    		return abs(k-oth.k)<=eps&&abs(b-oth.b)<=eps;
    	}
    };
    point cross(line A,line B){
    	if(A.k>=1e18-eps){
    		return point(A.b,A.b*B.k+B.b);
    	}
    	if(B.k>=1e18-eps){
    		return point(B.b,B.b*A.k+A.b);
    	}
    	lb x,y;
    	x=(B.b-A.b)/(A.k-B.k);
    	y=x*A.k+A.b;
    	return point (x,y);
    }
    vector<point> p;
    vector<line> l; 
    int n,q;
    lb solve(){
    	point A,B;
    	scanf("%Lf%Lf%Lf%Lf",&A.x,&A.y,&B.x,&B.y);
    	if(A.x==-100000&&A.y==100000&&B.x==100000 &&B.y==-100000){
    		eps=1e-9;
    	}
    	A.x*=100.0;
    	A.y*=100.0;
    	B.x*=100.0;
    	B.y*=100.0;
    	l.clear(); 
    	line query;
    	bool swp=false;
    	if(abs(A.x-B.x)<eps){
    		swp=true;
    		swap(A.x,A.y);
    		swap(B.x,B.y);
    		for(auto &it: p) swap(it.x,it.y);
    	}
    	rep(i,p.size()){
    		l.PB(line(p[i],p[(i+1)%p.size()]));
    	}
    	query=line(A,B);
    //	printf("Query %.10Lf %.10Lf
    ",query.k,query.b);
    	vector<point> v;
    	for(auto it:l){
    //				printf("Line is %.10Lf %.10Lf
    ",it.k,it.b);
    		if(abs(it.k-query.k)>eps){
    //			cout<<"!"<<endl;
    			point pp=cross(it,query);
    			if(it.in(pp)){
    //				printf("(%.10Lf %.10Lf)
    ",pp.x,pp.y);
    				v.PB(pp);
    			}
    		}
    	}
    	sort(ALL(v));
    	v.erase(unique(ALL(v)),v.end());
    	rb(i,0,p.size()-1){
    		point pre,nex;
    		pre=p[(i-1+p.size())%p.size()];
    		nex=p[(i+1)%p.size()];
    		line tmpl(pre,nex);
    		if(abs(tmpl.k-query.k)<=eps||!tmpl.strictin(cross(tmpl,query))){
    			auto ite=lower_bound(ALL(v),p[i]);
    //			cout<<"!"<<endl;
    //			printf("%.10Lf %.10Lf
    ",p[i].x,p[i].y);
    //			cout<<(ite==v.end())<<endl;
    			if(ite!=v.end()&&*ite==p[i]){
    //				cout<<"Era"<<endl;
    				v.erase(ite);
    			}
    		}
    	}
    	vector<pair<lb,lb> > xc;
    	for(auto it:v){
    		xc.PB(II(it.x,it.x));
    	}
    	lb rest=0.0;
    	vector<pair<lb,lb> > cover;
    	rep(i,n){
    		line now(p[i],p[(i+1)%p.size()]);
    		if(now==query){
    			line pn(p[(i-1+p.size())%p.size()],p[(i+2)%p.size()]);
    			if(pn.in(cross(pn,query))){
    				xc.PB(II(p[i].x,p[(i+1)%p.size()].x));
    				if(xc[xc.size()-1].FIR>xc[xc.size()-1].SEC) swap(xc[xc.size()-1].FIR,xc[xc.size()-1].SEC);
    			}
    			else{
    				cover.PB(II(p[i].x,p[(i+1)%p.size()].x));
    				if(cover[cover.size()-1].FIR>cover[cover.size()-1].SEC){
    					swap(cover[cover.size()-1].FIR,cover[cover.size()-1].SEC);
    				}
    			}
    		}
    	}
    	sort(ALL(xc));
    	xc.erase(unique(ALL(xc)),xc.end());
    	if(xc.size()%2==1){
    		puts("ERRO");
    		assert(0);
    	}
    	rep(i,xc.size()){
    		lb l,r;
    		l=xc[i].FIR;
    		r=xc[i+1].SEC;
    		if(l>r) swap(l,r);
    		cover.PB(II(l,r));
    		i++;
    	}
    	sort(ALL(cover));
    	double las=-1e18;
    	double bg=-1e18;
    	for(auto it:cover){
    		if(it.FIR+eps>las){
    			rest+=las-bg;
    			bg=it.FIR;
    			if(it.SEC>las)
    				las=it.SEC;
    		}
    		else{
    			if(it.SEC>las)
    				las=it.SEC;
    		}
    	}
    	rest+=las-bg;
    	lb h=rest*query.k;
    	rest=sqrt(rest*rest+h*h);
    	if(swp){
    		for(auto &it: p) swap(it.x,it.y);
    	}
    	return rest;
    }
    bool era[1001]; 
    void process(){
    	rep(i,n){
    		point pre,nex;
    		pre=p[(i-1+p.size())%p.size()];
    		nex=p[(i+1)%p.size()];
    		if(line(pre,p[i])==line(nex,p[i])) era[i]=true;
    	}
    	vector<point > neww;
    	rep(i,n) if(!era[i]) neww.PB(p[i]);
    	p=neww;
    	n=p.size();
    }
    int main(){
    	scanf("%d%d",&n,&q);
    	rb(i,1,n){
    		lb x,y;
    		scanf("%Lf%Lf",&x,&y);
    		x*=100.0;
    		y*=100.0;
    		p.PB(point (x,y));
    	}
    	process();//删除大小为Π的角 
    //	cout<<n<<endl;
    	bool ok=0;
    	rb(i,1,q){
    		lb rest=solve()/100.0;
    		printf("%.15Lf
    ",rest);
    	}
    	return 0;
    }
    /*
    3 7
    99999.99 -100000
    -100000 100000
    -99999.99 100000
    -100000 100000 100000 -100000
    */
    
  • 相关阅读:
    C#中如何创建文件夹,复制文件夹,删除文件夹的方法
    Entity Framework 4.1 CodeFirst 学习笔记
    c#使用豆瓣API
    字符串json转换为xml xml转换json
    基于方法的查询语法(1)
    A lowlevel Look at the ASP.NET Architecture
    删除sql表中重复数据
    关于document.cookie的使用
    大话设计模式之设计模式遵循的七大原则
    Cookies揭秘 [Asp.Net, Javascript]
  • 原文地址:https://www.cnblogs.com/gary-2005/p/14186575.html
Copyright © 2020-2023  润新知