版权声明:转载请声明出处,谢谢配合。 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;
}