Freda的城堡遭受了 M 个入侵者的攻击!
Freda控制着 N 座导弹防御塔,每座塔都有足够数量的导弹,但是每次只能发射一枚。
在发射导弹时,导弹需要 T1 秒才能从防御塔中射出,而在发射导弹后,发射这枚导弹的防御塔需要 T2 分钟来冷却。
所有导弹都有相同的匀速飞行速度 V,并且会沿着距离最短的路径去打击目标。
计算防御塔到目标的距离Distance时,你只需要计算水平距离,而忽略导弹飞行的高度。
导弹在空中飞行的时间就是 (Distance/V) 分钟,导弹到达目标后可以立即将它击毁。
现在,给出 N 座导弹防御塔的坐标,M 个入侵者的坐标,T1,T2 和 V。因为Freda的小伙伴Rainbow就要来拜访城堡了,你需要求出至少多少分钟才能击退所有的入侵者。
输入格式
第一行五个正整数N,M,T1,T2,V。
接下来 M 行每行两个整数,代表入侵者的坐标。
接下来 N 行每行两个整数,代表防御塔的坐标。
输出格式
输出一个实数,表示最少需要多少分钟才能击中所有的入侵者,四舍五入保留六位小数。
数据范围
1≤N,M≤50,坐标绝对值不超过10000,T1,T2,V不超过2000。
输入样例:
3 3 30 20 1
0 0
0 50
50 0
50 50
0 1000
1000 0
输出样例:
91.500000
坑点:
- T1是秒,得转化为分钟。
- match和vis以及a数组的第二个维度得开到n * m,多重匹配题不要有惯性思维!
#include <bits/stdc++.h>
using namespace std;
int n, m;
double t1, t2, v;
struct pos{ double x, y;};
pos tower[55], invader[55];
int a[55][2505] = {0};//第一维是m(左部) 第二维是n*p(右部)
bool vis[2505];
int match[2505];
double calc(double x1, double y1, double x2, double y2){ return sqrt(1ll * (x1 - x2) * (x1 - x2) + 1ll * (y1 - y2) * (y1 - y2)); }
bool dfs(int x, int up)
{
for(int i = 1, y; i <= up; i++)
{
if(!vis[y = i] && a[x][y])
{
vis[y] = 1;
if(!match[y] || dfs(match[y], up))
{
match[y] = x;//match vis得开到n*m
return 1;
}
}
}
return 0;
}
bool check(double mid)
{
memset(a, 0, sizeof(a));
memset(match, 0, sizeof(match));
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)//右部每个导弹发射塔拆成p个点 第i座塔发射到第j枚
{
for(int k = 1; k <= m; k++)//枚举入侵者
{
double ttime = calc(invader[k].x, invader[k].y, tower[i].x, tower[i].y) / v + 1.0 * (j - 1) * (t1 + t2) + 1.0 * t1;
if(ttime <= mid) a[k][(i - 1) * m + j] = 1;
}
}
}
for(int i = 1; i <= m; i++)
{
memset(vis, 0, sizeof(vis));
if(!dfs(i, n * m)) return 0;
}
return 1;
}
int main()
{
cin >> n >> m >> t1 >> t2 >> v;
t1 /= 60.0;
for(int i = 1; i <= m; i++) scanf("%lf%lf", &invader[i].x, &invader[i].y);
for(int i = 1; i <= n; i++) scanf("%lf%lf", &tower[i].x, &tower[i].y);
double l = 0, r = 1e5;//最长时间
while(r - l > 1e-8)
{
double mid = (l + r) / 2;
if(check(mid)) r = mid;
else l = mid;
}
printf("%.6lf", l);
return 0;
}