• 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;
    } 
    
  • 相关阅读:
    一个购物网站的思路设计分享
    B/S和C/S的区别(转)
    TreeSet
    计算出给你一个随机乱敲的一个字符串最多的一个
    JavaScript来实现打开链接页面(转载)
    js小数计算小数点后显示多位小数(转)
    java中使用 正则 抓取邮箱
    浅谈 正则表达式
    jQuery中each()、find()、filter()等节点操作方法
    Xcode插件VVDocumenter Alcatraz KSImageNamed等安装
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/13430534.html
Copyright © 2020-2023  润新知