hlg1481 Attack of the Giant n-pus【二分+二分图】

Attack of the Giant n-pus
Time Limit: 2000 MSMemory Limit: 65536 K
Total Submit: 71(6 users)Total Accepted: 8(5 users)Rating: Special Judge: No
Description

A pirate ship is being attacked by a giant n-pus(hint 1) . The n tentacles and the head of the creature

have pierced the deck and are wreaking havoc on the ship. In an attempt to stop the creature

from completely destroying the ship, the captain charges towards the head of the creature. Un-

fortunately, he quickly gets knocked back by one of the tentacles. The captain realizes he cannot

attack the head of the n-pus as long as it can move its tentacles freely.

Luckily the captain is not alone on the ship. There are p (p ≥ n) pirates spread around on the

deck, ready to follow the captain’s orders. So the captain comes up with the following plan. If

each tentacle is attacked by one of the pirates, he can move freely towards the head of the creature

and finish it off. To be safe, the captain will start moving only after each of the tentacles is being

attacked by a pirate. When the captain reaches the head, he can instantly kill the creature. The

captain wants to figure out which pirates to send to which tentacles, such that the creature can

be killed as fast as possible. As this happens regularly to pirates, the captain wants you to write

a program to solve this problem.

Input

The first line of the input contains a single number: the number of test cases to follow. Each test

case has the following format:

• One line with two integers n and p, satisfying 1 ≤ n ≤ p ≤ 100: the number of tentacles of

  the n-pus and the number of pirates (excluding the captain), respectively.

• One line with three integers xc , yc and vc : the captain’s coordinates and speed, respectively.

• p lines, each with three integers xi , yi and vi : the coordinates and speed, respectively, of

  each pirate.

• One line with two integers xh and yh : the coordinates of the head of the n-pus.

• n lines, each with two integers xj and yj : the coordinates of each tentacle.

All coordinates satisfy 0 ≤ x, y ≤ 10, 000. All speeds satisfy 1 ≤ v ≤ 100.

The captain, the pirates, the head and the tentacles are all considered to be point-like (i.e. they

have no size). Their locations are all distinct.

The captain and all pirates move to their target in a straight line at their given speed and are not

hindered by anyone or anything.

Output

For every test case in the input, the output should contain one floating point number on a single

line: the minimum time it takes for the captain to kill the n-pus. Your answer should have either

an absolute or a relative error of at most 10^−6 .

Sample Input

3 3 
2 0 1 
0 0 2
1 0 3
3 0 4
2 3
0 1
1 1
4 1
1 3
0 0 1
3 0 1
4 0 1
7 0 2
0 1
4 2
3 3
0 0 2
2 0 3
3 0 1
4 0 2
0 1
3 1
4 1
5 1
Sample Output
3.500000000
2.802775638
1.500000000
Hint

1. An n-pus is like an octopus, but then with n tentacles.

 

原始题目的输出需要Special Judge,为了方便,输出答案时请精确到小数点后9位。

Source
BAPC 2011 Preliminaries

 

 

这个困扰我三天的题终于解开了啊

好艰辛啊

5555~~~

 

大意:

一群水手去攻击一只只爪子的章鱼

告诉你每个水手的位置和前进的速度

又告诉你每个章鱼爪子的位置

告诉你章鱼头部的位置又告诉你船长的位置和速度

船长只有在所有的爪子被水手控制的情况下才会去攻击章鱼的头部

问最后船长攻击到章鱼头部的最短时间

要求精度误差在0.000000001之内

 

分析:

二分枚举发动攻击的时间,如果在该时间内水手能够抵达一只爪子就建立一条边

最后求得结果

 

不得不去吐槽一下啊

黄老师不加sj还要求那么高的精度

简直就是丧心病狂啊

开始的时候一直TLE

然后发现一个可以大大提高时间的地方就是事先处理出每个水手到每只爪子的距离

然后还是TLE啊啊啊

然后看周洲的代码

发现他是用手写的邻接表

我想不能吧  这么丧心病狂

vector应该比邻接表慢不了几倍的速度吧

我就改成邻接表储存

结果

就a了

瞬间石化

 

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <vector>
  6 using namespace std;
  7 
  8 const int maxn = 101;
  9 
 10 int n, p;
 11 
 12 struct Edge
 13 {
 14     int to,next;
 15 }e[10002];
 16 int head[maxn];
 17 int tot;
 18 void add(int s,int u)
 19 {
 20     e[tot].to = u;
 21     e[tot].next = head[s];
 22     head[s] = tot++;
 23 }
 24 
 25 double xi[maxn], yi[maxn], vi[maxn];
 26 double xj[maxn], yj[maxn];
 27 double dist[maxn][maxn];
 28 
 29 int vis[maxn], Link[maxn];
 30 
 31 bool Find(int u) {
 32     for(int i = head[u]; i; i = e[i].next) {
 33         int v = e[i].to;
 34         if(!vis[v]) {
 35             vis[v] = 1;
 36             if(Link[v] == -1 || Find(Link[v]) ) {
 37                 Link[v] = u;
 38                 return true;
 39             }
 40         }
 41     }
 42     return false;
 43 }
 44 
 45 bool Match() {
 46     memset(Link, -1, sizeof(Link));
 47     for(int i = 1; i <= n; i++) {
 48         memset(vis, 0, sizeof(vis));
 49         if(!Find(i) ) return false;
 50     }
 51     return true;
 52 }
 53 
 54 double Dist(double x1, double y1, double x2, double y2) {
 55     double xx = x1 - x2;
 56     double yy = y1 - y2;
 57     return sqrt(xx * xx + yy * yy );
 58 }
 59 
 60 bool check(double mid) {
 61     tot = 1; memset(head, 0, sizeof(head));
 62     for(int i = 1; i <= n; i++) {
 63         for(int j = 1; j <= p; j ++) {
 64             if(dist[i][j] < mid) {
 65                 add(i, j);
 66             }
 67         }
 68     }
 69     if(Match()) {
 70         return true;
 71     }
 72     return false;
 73 }
 74 
 75 const double wucha = 0.0000000001;
 76 
 77 int main() {
 78     double xc, yc, vc;
 79     double xh, yh;
 80     int t;
 81     //freopen("test.txt","r",stdin);
 82     scanf("%d",&t);
 83     while(t--) {
 84         scanf("%d %d",&n, &p);
 85         scanf("%lf %lf %lf", &xc, &yc, &vc);
 86         for(int i = 1;  i <= p; i++) {
 87             scanf("%lf %lf %lf", &xi[i], &yi[i], &vi[i]);
 88         }
 89         scanf("%lf %lf", &xh, &yh);
 90         for(int i = 1; i <= n; i++) {
 91             scanf("%lf %lf", &xj[i], &yj[i]);
 92         }
 93         double low = 0, high = 0;
 94         for(int i = 1;i <= n; i++) {
 95             for(int j = 1; j <= p; j++) {
 96                 dist[i][j] = Dist(xj[i], yj[i], xi[j], yi[j]) * 1.0 / vi[j];
 97                 if(dist[i][j] > high) high = dist[i][j];
 98             }
 99         }
100         while(low < high) {
101             double mid = (low + high) * 0.5;
102             if(!check(mid)) {
103                 low = mid + wucha;
104             } else {
105                 high = mid - wucha;
106             }
107         }
108         double ans = high + wucha;
109         ans += (Dist(xc, yc, xh, yh) / vc);
110         printf("%.9lf\n", ans);
111     }
112     return 0;
113 }
View Code

 

转载于:https://www.cnblogs.com/zhanzhao/p/3980639.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值