Codevs2490 导弹防御塔

2490 导弹防御塔

2490 导弹防御塔

 

时间限制: 1 s
空间限制: 64000 KB
题目等级 : 大师 Master
 
 
 
 
题目描述 Description

  Freda的城堡——
  “Freda,城堡外发现了一些入侵者!”
  “喵...刚刚探究完了城堡建设的方案数,我要歇一会儿嘛lala~”
  “可是入侵者已经接近城堡了呀!”
  “别担心,rainbow,你看呢,这是我刚设计的导弹防御系统的说~”
  “喂...别卖萌啊……”

  Freda控制着N座可以发射导弹的防御塔。每座塔都有足够数量的导弹,但是每座塔每次只能发射一枚。在发射导弹时,导弹需要T1秒才能从防御塔中射出,而在发射导弹后,发射这枚导弹的防御塔需要T2分钟来冷却。
  所有导弹都有相同的匀速飞行速度V,并且会沿着距离最短的路径去打击目标。计算防御塔到目标的距离Distance时,你只需要计算水平距离,而忽略导弹飞行的高度。导弹在空中飞行的时间就是 (Distance/V) 分钟,导弹到达目标后可以立即将它击毁。
  现在,给出N座导弹防御塔的坐标,M个入侵者的坐标,T1、T2和V,你需要求出至少要多少分钟才能击退所有的入侵者。

输入描述 Input Description

  第一行五个正整数N,M,T1,T2,V。
  接下来M行每行两个整数,代表入侵者的坐标。
  接下来N行每行两个整数,代表防御塔的坐标。

输出描述 Output Description

  输出一个实数,表示最少需要多少分钟才能击中所有的入侵者,四舍五入保留六位小数。

样例输入 Sample Input

3 3 30 20 1
0 0
0 50
50 0
50 50
0 1000
1000 0

样例输出 Sample Output

91.500000

数据范围及提示 Data Size & Hint

  对于40%的数据,N,M<=20.
  对于100%的数据, 1≤N≤50, 1≤M≤50,坐标绝对值不超过10000,T1,T2,V不超过2000.

来源:Nescafe 19

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
【题解】
二分答案,让每个炮台发射尽量多的导弹,即把一个炮台拆成很多个点,
看每个点能不能打到某个入侵者,打到就往入侵者连边
注意二分上界
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <cmath>
  6 #define max(a, b) ((a) > (b) ? (a) : (b))
  7 #define min(a, b) ((a) < (b) ? (a) : (b)) 
  8 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 
  9 
 10 const int INF = 0x3f3f3f3f;
 11 const double eps = 0.0000001;
 12 const int MAXN = 50 + 10;
 13 
 14 inline void read(int &x)
 15 {
 16     x = 0;char ch = getchar(), c = ch;
 17     while(ch < '0' || ch > '9')c = ch, ch = getchar();
 18     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
 19     if(c == '-') x = -x;
 20 }
 21 
 22 int n,m,t1,t2;
 23 double v;
 24 int tax[MAXN],tay[MAXN],qinx[MAXN],qiny[MAXN];
 25 int g[100000][MAXN], lk[MAXN], b[MAXN];
 26 int tot;
 27 
 28 inline double dis(int a, int b)
 29 {
 30     return sqrt(abs(tax[a] - qinx[b]) * abs(tax[a] - qinx[b]) + abs(tay[a] - qiny[b]) * abs(tay[a] - qiny[b]));
 31 }
 32 
 33 //-1:> 0:= 1:< 
 34 int cmp(double a, double b)
 35 {
 36     if(abs(a - b) <= eps)return 0;
 37     return a - b < 0 ? 1 : -1;
 38 } 
 39 
 40 int dfs(int u)
 41 {
 42     for(register int i = 1;i <= m;++ i)
 43     {
 44         if(!b[i] && g[u][i])
 45         {
 46             b[i] = 1;
 47             if(lk[i] == -1 || dfs(lk[i]))
 48             {
 49                 lk[i] = u;
 50                 return 1;
 51             }
 52         }
 53     }
 54     return 0;
 55 }
 56 
 57 int xiongyali()
 58 {
 59     int ans = 0;
 60     memset(lk, -1, sizeof(lk));
 61     for(register int i = 1;i <= tot;++ i)
 62     {
 63         memset(b, 0, sizeof(b));
 64         ans += dfs(i);
 65     }
 66     return ans;
 67 }
 68 
 69 int check(double ma)
 70 {
 71     memset(g, 0, sizeof(g));
 72     tot = 0;
 73     //枚举炮台 
 74     for(register int i = 1;i <= n;++i)
 75     {
 76         //发射时间 
 77         for(register double now = t1;cmp(now, ma) != -1;now += t2 + t1)
 78         {
 79             ++ tot;
 80             //看能到达的入侵者 
 81             for(register int j = 1;j <= m;++ j)
 82             {
 83                 if(cmp(now + dis(i,j) / v, ma) != -1)
 84                     g[tot][j] = 1;
 85             }
 86         }
 87     }
 88     if(xiongyali() == m) return 1;
 89     return 0;
 90 }
 91 
 92 int main()
 93 {
 94     scanf("%d %d %d %d %lf", &n, &m, &t1, &t2, &v);
 95     t2 *= 60;v = v/60;
 96     for(register int i = 1;i <= m;++ i)
 97         scanf("%d %d", &qinx[i], &qiny[i]);
 98     for(register int j = 1;j <= n;++ j)
 99         scanf("%d %d", &tax[j], &tay[j]);
100     double l = 1, r = 1400000, mid, ans = 0;
101     while(cmp(l + eps, r) == 1)
102     {
103         mid = (l + r) / 2; 
104         if(check(mid))r = mid, ans = mid;
105         else l = mid;
106     } 
107     printf("%.6f", ans/60);
108     return 0;
109 }
Codevss2490