2019.03.07【SDOI2018】【洛谷P4605】【BZOJ5328】物理实验(扫描线)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/88358988

洛谷传送门

BZOJ传送门


解析:

没什么难度的计算几何模拟题,直接上斜着的扫描线就行了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define cs const

namespace IO{
	inline char get_char(){
		static cs int Rlen=1<<20|1;
		static char buf[Rlen],*p1,*p2;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	
	inline int getint(){
		re char c;
		re bool f=0;
		while(!isdigit(c=gc()))if(c=='-')f=1;re int num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return f?-num:num;
	}
}
using namespace IO;

cs int N=1e4+4;

struct Point{
	int x,y;
	Point(){}
	Point(cs int &_x,cs int &_y):x(_x),y(_y){}
	void read(){x=getint(),y=getint();}
	friend Point operator+(cs Point &a,cs Point &b){return Point(a.x+b.x,a.y+b.y);}
	friend Point operator-(cs Point &a,cs Point &b){return Point(a.x-b.x,a.y-b.y);}
	friend ll operator*(cs Point &a,cs Point &b){return (ll)a.x*b.y-(ll)a.y*b.x;}
	friend ll dot(cs Point &a,cs Point &b){return (ll)a.x*b.x+(ll)a.y*b.y;}
	double norm()cs{return sqrt((ll)x*x+(ll)y*y);}
}p1[N],p2[N],p3,p4,v;

ll d1[N],d2[N];
int n,L;

struct line_pos{
	int id,flag;
	ll d;
	friend bool operator<(cs line_pos &a,cs line_pos &b){return a.d<b.d;}
}p[N<<1];
bool dir[N];
ll a[N<<1];
double su[N<<1];
int tot,cnt;

struct atom0{
	int id;
	friend bool operator<(cs atom0 &a,cs atom0 &b){
		return d2[a.id]>d2[b.id]?
		(p2[a.id]-p2[b.id])*(p1[b.id]-p2[b.id])>0:
		(p2[b.id]-p2[a.id])*(p1[a.id]-p2[a.id])<0;
	}
};
set<atom0> s0;
set<atom0>::iterator i0[N];
struct atom1{
	int id;
	friend bool operator<(cs atom1 &a,cs atom1 &b){
		return d2[a.id]>d2[b.id]?
		(p2[a.id]-p2[b.id])*(p1[b.id]-p2[b.id])<0:
		(p2[b.id]-p2[a.id])*(p1[a.id]-p2[a.id])>0;
	}
};
set<atom1> s1;
set<atom1>::iterator i1[N];

inline void solve(){
	n=getint();
	for(int re i=1;i<=n;++i)p1[i].read(),p2[i].read();
	p3.read(),p4.read();L=getint();
	v=p3-p4;
	tot=cnt=0;
	for(int re i=1;i<=n;++i){
		if(dot(p1[i]-p4,v)<dot(p2[i]-p4,v))swap(p1[i],p2[i]);
		dir[i]=(p1[i]-p4)*v>=0;
		p[++tot]=(line_pos){i,-1,d1[i]=dot(p1[i]-p4,v)};
		p[++tot]=(line_pos){i,1,d2[i]=dot(p2[i]-p4,v)};
	} 
	sort(p+1,p+tot+1);
	for(int re i=1,j;i<=tot;++i){
		a[++cnt]=p[i].d;
		if(cnt>1){
			su[cnt-1]=0;
			if(!s1.empty()){
				j=s1.begin()->id;
				su[cnt-1]+=(p1[j]-p2[j]).norm()*(a[cnt]-a[cnt-1])/(d1[j]-d2[j]);
			}
			if(!s0.empty()){
				j=s0.begin()->id;
				su[cnt-1]+=(p1[j]-p2[j]).norm()*(a[cnt]-a[cnt-1])/(d1[j]-d2[j]);
			}
		}
		while(true){
			if(dir[p[i].id]){
				if(p[i].flag==1)i1[p[i].id]=s1.insert((atom1){p[i].id}).first;
				else s1.erase(i1[p[i].id]);
			}
			else {
				if(p[i].flag==1)i0[p[i].id]=s0.insert((atom0){p[i].id}).first;
				else s0.erase(i0[p[i].id]);
			}
			if(i==tot||p[i].d!=p[i+1].d)break;
			++i;
		}
	}
	double len=L*v.norm(),sum=0,ans=0,tmp;
	for(int re i=1,j=1;i<=cnt;++i){
		for(;j<cnt&&a[j+1]-a[i]<=len;++j)sum+=su[j];
		tmp=sum;
		if(j<cnt)tmp+=su[j]*(len-(a[j]-a[i]))/(a[j+1]-a[j]);
		ans=max(ans,tmp);
		if(j>i)sum-=su[i];
		else ++j;
	}
	for(int re i=cnt,j=cnt;i;--i){
		for(;j>1&&a[i]-a[j-1]<=len;--j)sum+=su[j-1];
		tmp=sum;
		if(j>1)tmp+=su[j-1]*(len-(a[i]-a[j]))/(a[j]-a[j-1]);
		ans=max(ans,tmp);
		if(j<i)sum-=su[i-1];
		else --j;
	}
	printf("%.8f\n",ans);
}

int T;
signed main(){
	T=getint();
	while(T--)solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/88358988