Loading

CH6803 导弹发射塔(二分图最大匹配/多重匹配)

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

坑点:

  1. T1是秒,得转化为分钟。
  2. 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;
} 
posted @ 2020-08-03 23:01  脂环  阅读(190)  评论(0编辑  收藏  举报