建图+二分图+二分

//#define LOCAL
#include <bits/stdc++.h>

using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define DNF 0x7f
#define DBG printf("this is a input\n")
#define fi first
#define se second
#define mk(a, b) make_pair(a,b)
#define pb push_back
#define p_queue priority_queue
#define eps 1e-8
ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a % b);
}

ll lcm(ll a, ll b) {
    return a / gcd(a, b) * b;
}
int n , m, cx;
double t1, t2, v;
int head[100005] , cnt;
double dis[55][55];
struct node{
    double x, y;
}r[55], f[55];
struct e
{
    int t, next;
}edge[1000*1000];
void add(int f, int t)
{
    edge[cnt].t = t;
    edge[cnt].next = head[f];
    head[f] = cnt ++;
}
int fa[100005] , vis[100005];
double DIS(int i , int j)
{
    return sqrt ((f[i].x - r[j].x)*(f[i].x - r[j].x) + (f[i].y - r[j].y)*(f[i].y - r[j].y) );
}
bool dfs(int root)
{
    for(int i = head[root] ; i != -1 ; i = edge[i].next)
    {
        int t = edge[i].t;
        if(!vis[t])
        {
            vis[t] = 1;
            if(!fa[t] || dfs(fa[t]))
            {
                fa[t] = root;
                return true;
            }
        }
    }
    return false;
}
bool check(double x)
{
    mem(head,-1);
    cnt = 0;
    cx = 0;
    for(int i = 1 ; i <= n ; i ++) //防御
    {
        double now = t1;
        while(now <= x)
        {
            cx ++;
            for(int j = 1 ; j <= m ; j ++) //敌人
            {
                if(dis[i][j]/v + now <= x)
                    add(cx, j); //i j 都有可能为相同值故双向边会出错,除非编号不相同
            }
            now += (t2+t1);
        }
    }
    mem(fa,0);
    int ans = 0;
    for(int i = 1 ; i <= cx ; i ++)
    {
        mem(vis,0);
        if(dfs(i)) ans ++;
        if(ans == m) return true;
    }
    return false;
}
int main(void)
{
#ifdef LOCAL
    freopen("data.in", "r", stdin);
    freopen("odata.out", "w", stdout);
#endif
    cin>>n>>m>>t1>>t2>>v;
    t1 /= 60.0;
    for(int i = 1 ; i <= m ; i ++)
        cin>>r[i].x>>r[i].y;
    for(int i = 1 ; i <= n ; i ++)
        cin>>f[i].x>>f[i].y;
    for(int i = 1 ; i <= n ; i ++)
        for(int j = 1; j <= m ; j ++)
            dis[i][j] = DIS(i,j);
    double l = 0 , r = 100000.0;
    while(r - l > eps)
    {
        double mid = (l + r) / 2.0;
        if(check(mid)) r = mid;
        else l = mid;
    }
    printf("%.6lf\n",r);
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值