Attack of the Giant n-pus | ||||||
| ||||||
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 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 }