二分+最大匹配,把每个发射塔拆成m个点,与每个导弹相连。第i个塔的第j个点代表第i个塔第j次发射的导弹,边长为 j*(t1/60) + (j-1)*t2 + dis(i,k);K为第k个目标。然后二分答案,边长小于答案的边留下,最后剩下个0/1矩阵,再求最大匹配。
/*
* Author: xioumu
* Created Time: 2011-10-25 23:13:42
* File Name: p3460.cpp
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define MAXNUM 200000000
#define esp 1e-8
#define MAXN 107
using namespace std;
int n,m,t1,t2,sp;
int xx[MAXN],yy[MAXN];
double map[MAXN*MAXN][MAXN];
int vv[MAXN*MAXN][MAXN];
double dis(double x1,double y1,double x2,double y2)
{
return sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
}
void init()
{
int i,j,k,r,w;
for(i=1;i<=m;i++)
scanf("%d %d",&xx[i],&yy[i]);
for(i=m+1;i<=n+m;i++)
scanf("%d %d",&xx[i],&yy[i]);
memset(map,0,sizeof(map));
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
for(k=1;k<=m;k++)
map[ (i-1)*m+j ][k] = (t1*1.0/60)*j + t2*(j-1) + dis(xx[k],yy[k],xx[i+m],yy[i+m])/sp;
}
int fa[MAXN],v[MAXN];
int xiong(int w)
{
int i,j,k,r;
for(i=1;i<=m;i++)
{ if(vv[w][i] == 1 && v[i] == 0)
{ v[i] = 1;
if( fa[i] == 0 || xiong( fa[i] ))
{ fa[i] = w;
return 1;
}
}
}
return 0;
}
int fun(double h)
{
int i,j,k,r,w;
//memset(a,0,sizeof(a));
for(i=1;i<=n*m;i++)
for(j=1;j<=m;j++)
vv[i][j] = 0;
for(i=1;i<=n*m;i++)
for(j=1;j<=m;j++)
if(map[i][j] <= h)
{ vv[i][j] = 1;
//vv[j][i] = 1;
}
//for(i=1;i<=n*m;i++,printf("\n"))
//for(j=1;j<=m;j++)
//printf("%0.2f ",h);
//printf("\n");
memset(fa,0,sizeof(fa));
w = 0;
for(i=1;i<=n*m;i++)
{ memset(v,0,sizeof(v));
if( xiong(i) )
w++;
}
//printf("%d\n",w);
if(w == m) return 1;
else return 0;
}
void solve()
{
int i,j,k,r,w;
double x,y,mid,ans;
ans = MAXNUM;
x = 0;
y = MAXNUM;
while( fabs(y-x) > 1e-8)
{ mid = (x+y)/2;
if( fun(mid) ) { ans = mid; y = mid; }
else x = mid;
}
printf("%.6f\n",ans);
}
int main()
{
//freopen("p3460.in","r",stdin);
while( scanf("%d %d %d %d %d",&n,&m,&t1,&t2,&sp) != EOF)
{ init();
solve();
}
return 0;
}