二分时间。
固定时间后,每个防御塔发射炮弹数量是固定的。
每枚炮弹可打的敌人也是固定的。
相当于一个多重匹配,左部图一个可匹配多个,有部图一个只能匹配一个。
把左部图拆成多个点,进行最大匹配。
#include <bits/stdc++.h>
using namespace std;
typedef long double ld;
typedef long long ll;
const int M = 2e5+7;
const ld eps= 1e-10;
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
struct node{
ld x,y;
}a[60],d[60];
int match[M],vs[M];
int n,m,q;
ld t1,t2,v;
ld dis[60][60];
ld gt_dis(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool dfs(int x)
{
for(int i=head[x];i;i=ee[i].nxt)
{
int y=ee[i].to;
if(!vs[y])
{
vs[y]=1;
if(!match[y]||dfs(match[y]))
{
match[y]=x;//y点与x匹配
return true;
}
}
}
return false;
}
bool ck(ld x)//能否在x分钟内解决敌人
{
int nm=0;
for(int i=1;i<=m;i++)//发射i枚炮弹用时
if(i*t1+t2*(i-1)<=x)nm=i;
int ans=0;
if(nm==0)return false;;
memset(head,0,sizeof(head));
memset(match,0,sizeof(match));
cnt=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=nm;j++)
{
ld di=(x-t1*j-t2*(j-1))*v;//这一枚炮弹能打多远的敌人
for(int k=1;k<=m;k++)
if(dis[i][k]<=di)add((i-1)*nm+j,k+n*nm),add(k+n*nm,(i-1)*nm+j);
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=nm;j++)
{
memset(vs,0,sizeof(vs));
if(dfs((i-1)*nm+j))ans++;
// cout<<i<<" "<<j<<" "<<ans<<endl;
}
if(ans>=m)return true;
return false;
}
int main()
{
cin>>n>>m>>t1>>t2>>v;
t1/=60;
for(int i=1;i<=m;i++)cin>>a[i].x>>a[i].y;
for(int i=1;i<=n;i++)cin>>d[i].x>>d[i].y;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
dis[j][i]=gt_dis(a[i],d[j]);
ld l=1,r=100100,ans=0;
while(l+eps<=r)
{
// cout<<"-----------"<<l<<" "<<r<<endl;
ld mid=(l+r)/2;
if(ck(mid))ans=mid,r=mid;
else l=mid;
}
printf("%.6Lf\n",ans);
return 0;
}