题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4063

Description

You are playing a flying game. 
In the game, player controls an aircraft in a 2D-space. 
The mission is to drive the craft from starting point to terminal point. 
The craft needs wireless signal to move. 
A number of devices are placed in the 2D-space, spreading signal. 
For a device Di, it has a signal radius -- Ri. 
When the distance between the craft and Di is shorter or equal to Ri, it(the craft) gets Di's wireless signal. 
Now you need to tell me the shortest path from starting point to terminal point. 
 

Input

The first line of the input file is a single integer T. 
The rest of the test file contains T blocks. 
Each block starts with an integer n, followed by n devices given as (xi, yi, Ri). 
(xi, yi) is position of Di, and Ri is the radius of its signal range. 
The first point is the starting point. 
The last point is the terminal point. 
T <= 25; 
2 <= n <= 20 for most cases; 
20 < n <= 25 for several cases, completely random generated. 
-1000 <= xi, yi <= 1000 , 1 <= ri <= 1000. 
All are integers.
 

Output

For each case, Output "No such path." if the craft can't get to the terminal point. 
Otherwise, output a float number, correct the result to 4 decimal places.(as shown in the sample output) 
 
题目大意&题解:http://blog.csdn.net/zxy_snow/article/details/6849550
PS:首位共点的时候一直输出No such path没发现调了半天……
 
下面是用计算几何的方法,不知为何G++一直TLE(难道是我写错了?),可能是因为加入了大量的函数运算然后没有被优化……
顺便贴个模板
 
代码(C++ 750MS):
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <cmath>
  6. using namespace std;
  7. typedef long long LL;
  8.  
  9. const int MAXN = ;
  10. const int MAXV = MAXN * MAXN * ;
  11. const int MAXE = MAXV * MAXV;
  12. const double EPS = 1e-;
  13. const double INF = 1e100;
  14.  
  15. inline double sqr(double x) {
  16. return x * x;
  17. }
  18.  
  19. inline int sgn(double x) {
  20. return (x > EPS) - (x < -EPS);
  21. }
  22.  
  23. struct Point {
  24. double x, y;
  25. Point() {}
  26. Point(double x, double y): x(x), y(y) {}
  27. void read() {
  28. scanf("%lf%lf", &x, &y);
  29. }
  30. bool operator < (const Point &rhs) const {
  31. if(sgn(x - rhs.x) != ) return x < rhs.x;
  32. return sgn(y - rhs.y) < ;
  33. }
  34. bool operator == (const Point &rhs) const {
  35. return sgn(x - rhs.x) == && sgn(y - rhs.y) == ;
  36. }
  37. Point operator + (const Point &rhs) const {
  38. return Point(x + rhs.x, y + rhs.y);
  39. }
  40. Point operator - (const Point &rhs) const {
  41. return Point(x - rhs.x, y - rhs.y);
  42. }
  43. double operator * (const Point &rhs) const {
  44. return x * rhs.x + y * rhs.y;
  45. }
  46. Point operator * (double d) const {
  47. return Point(x * d, y * d);
  48. }
  49. Point operator / (double d) const {
  50. return Point(x / d, y / d);
  51. }
  52. Point rotate() const {
  53. return Point(-y, x);
  54. }
  55. double length() const {
  56. return sqrt(*this * *this);
  57. }
  58. };
  59.  
  60. double dist(const Point &a, const Point &b) {
  61. return (a - b).length();
  62. }
  63.  
  64. double cross(const Point &a, const Point &b) {
  65. return a.x * b.y - a.y * b.x;
  66. }
  67.  
  68. double cross(const Point &o, const Point &a, const Point &b) {
  69. return cross(a - o, b - o);
  70. }
  71.  
  72. double Point_to_Line(const Point &p, const Point &st, const Point &ed) {
  73. return fabs(cross(p, st, ed)) / dist(st, ed);
  74. }
  75.  
  76. Point intersection(const Point &u1, const Point &u2, const Point &v1, const Point &v2) {
  77. double t = cross(u1 - v1, v1 - v2) / cross(u1 - u2, v1 - v2);
  78. return u1 + (u2 - u1) * t;
  79. }
  80.  
  81. struct Circle {
  82. Point c;
  83. double r;
  84. Circle() {}
  85. Circle(Point c, double r): c(c), r(r) {}
  86. void read() {
  87. c.read();
  88. scanf("%lf", &r);
  89. }
  90. bool contain(const Circle &rhs) const {
  91. return sgn(dist(c, rhs.c) + rhs.r - r) <= ;
  92. }
  93. bool contain(const Point &p) const {
  94. return sgn(dist(c, p) - r) <= ;
  95. }
  96. bool intersect(const Circle &rhs) const {
  97. return sgn(dist(c, rhs.c) - r - rhs.r) < ;
  98. }
  99. bool tangency(const Circle &rhs) const {
  100. return sgn(dist(c, rhs.c) - r - rhs.r) == ;
  101. }
  102. };
  103.  
  104. int intersection(const Circle &cir, const Point &st, const Point &ed, Point &p1, Point &p2) {
  105. if(sgn(Point_to_Line(cir.c, st, ed) - cir.r) > ) return ;
  106. Point p = cir.c + (ed - st).rotate();
  107. p = intersection(p, cir.c, st, ed);
  108. double t = sqrt(sqr(cir.r) - sqr(dist(p, cir.c))) / dist(st, ed);
  109. p1 = p + (ed - st) * t;
  110. p2 = p - (ed - st) * t;
  111. return - (p1 == p2);
  112. }
  113.  
  114. int intersection(const Circle &c1, const Circle &c2, Point &p1, Point &p2) {
  115. if(c1.contain(c2) || c2.contain(c1)) return ;
  116. if(!c1.intersect(c2) && !c1.tangency(c2)) return ;
  117. double t = 0.5 * ( + (sqr(c1.r) - sqr(c2.r)) / sqr(dist(c1.c, c2.c)));
  118. Point u = c1.c + (c2.c - c1.c) * t, v = u + (c1.c - c2.c).rotate();
  119. return intersection(c1, u, v, p1, p2);
  120. }
  121.  
  122. struct Graph {
  123. int head[MAXV], ecnt;
  124. int to[MAXE], next[MAXE];
  125. double cost[MAXE];
  126. int n, st, ed;
  127.  
  128. void init() {
  129. memset(head, -, sizeof(head));
  130. ecnt = ;
  131. }
  132.  
  133. void add_edge(int u, int v, double c) {
  134. to[ecnt] = v; cost[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
  135. to[ecnt] = u; cost[ecnt] = c; next[ecnt] = head[v]; head[v] = ecnt++;
  136. }
  137.  
  138. double dis[MAXV];
  139. bool vis[MAXV];
  140.  
  141. double dijksrta(int st, int ed, int n) {
  142. for(int i = ; i < n; ++i) dis[i] = INF;
  143. dis[st] = ;
  144. memset(vis, , sizeof(vis));
  145. while(true) {
  146. int u = -; double d = INF;
  147. for(int i = ; i < n; ++i) if(!vis[i])
  148. if(dis[i] < d) d = dis[i], u = i;
  149. if(d == INF) break;
  150. vis[u] = true;
  151. for(int p = head[u]; ~p; p = next[p]) {
  152. int &v = to[p];
  153. if(!vis[v]) dis[v] = min(dis[v], dis[u] + cost[p]);
  154. }
  155. }
  156. return dis[ed];
  157. }
  158. } G;
  159.  
  160. Circle cir[MAXN];
  161. int T, n;
  162.  
  163. Point list[MAXV];
  164.  
  165. bool havePath(Point st, Point ed) {
  166. if(ed < st) swap(st, ed);
  167. if(st == ed) return true;
  168. Point p1, p2;
  169. int pcnt = ;
  170. list[pcnt++] = st;
  171. list[pcnt++] = ed;
  172. for(int i = ; i < n; ++i) {
  173. int c = intersection(cir[i], st, ed, p1, p2);
  174. if(c >= ) list[pcnt++] = p1;
  175. if(c >= ) list[pcnt++] = p2;
  176. }
  177. sort(list, list + pcnt);
  178. for(int i = ; i < pcnt; ++i) {
  179. if(list[i] < st || list[i] == st) continue;
  180. bool flag = false;
  181. for(int j = ; j < n && !flag; ++j)
  182. if(cir[j].contain(list[i]) && cir[j].contain(list[i - ])) flag = true;
  183. if(!flag) return false;
  184. if(list[i] == ed) break;
  185. }
  186. return true;
  187. }
  188.  
  189. Point p[MAXV];
  190. int cnt;
  191.  
  192. double solve() {
  193. Point p1, p2;
  194. cnt = ;
  195. p[cnt++] = cir[].c; p[cnt++] = cir[n - ].c;
  196. for(int i = ; i < n; ++i) {
  197. for(int j = i + ; j < n; ++j) {
  198. int c = intersection(cir[i], cir[j], p1, p2);
  199. if(c >= ) p[cnt++] = p1;
  200. if(c >= ) p[cnt++] = p2;
  201. }
  202. }
  203. G.init();
  204. for(int i = ; i < cnt; ++i) {
  205. for(int j = i + ; j < cnt; ++j)
  206. if(havePath(p[i], p[j])) G.add_edge(i, j, dist(p[i], p[j]));
  207. }
  208. return G.dijksrta(, , cnt);
  209. }
  210.  
  211. int main() {
  212. scanf("%d", &T);
  213. for(int kase = ; kase <= T; ++kase) {
  214. scanf("%d", &n);
  215. for(int i = ; i < n; ++i) cir[i].read();
  216. double res = solve();
  217. if(res == INF) printf("Case %d: No such path.\n", kase);
  218. else printf("Case %d: %.4f\n", kase, res);
  219. }
  220. }

下面是用了一部分解析几何的方法,比上面的还要快……

代码(G++ 437MS):

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <cmath>
  6. #include <numeric>
  7. using namespace std;
  8. typedef long long LL;
  9.  
  10. const int MAXN = ;
  11. const int MAXV = MAXN * MAXN * ;
  12. const int MAXE = MAXV * MAXV;
  13. const double EPS = 1e-;
  14. const double INF = 1e100;
  15.  
  16. inline double sqr(double x) {
  17. return x * x;
  18. }
  19.  
  20. inline int sgn(double x) {
  21. return (x > EPS) - (x < -EPS);
  22. }
  23.  
  24. struct Point {
  25. double x, y;
  26. Point() {}
  27. Point(double x, double y): x(x), y(y) {}
  28. void read() {
  29. scanf("%lf%lf", &x, &y);
  30. }
  31. bool operator < (const Point &rhs) const {
  32. if(sgn(x - rhs.x) != ) return x < rhs.x;
  33. return sgn(y - rhs.y) < ;
  34. }
  35. bool operator == (const Point &rhs) const {
  36. return sgn(x - rhs.x) == && sgn(y - rhs.y) == ;
  37. }
  38. Point operator + (const Point &rhs) const {
  39. return Point(x + rhs.x, y + rhs.y);
  40. }
  41. Point operator - (const Point &rhs) const {
  42. return Point(x - rhs.x, y - rhs.y);
  43. }
  44. double operator * (const Point &rhs) const {
  45. return x * rhs.x + y * rhs.y;
  46. }
  47. Point operator * (double d) const {
  48. return Point(x * d, y * d);
  49. }
  50. Point operator / (double d) const {
  51. return Point(x / d, y / d);
  52. }
  53. Point rotate() const {
  54. return Point(-y, x);
  55. }
  56. double length() const {
  57. return sqrt(*this * *this);
  58. }
  59. };
  60.  
  61. double dist(const Point &a, const Point &b) {
  62. return (a - b).length();
  63. }
  64.  
  65. double cosIncludeAngle(const Point &a, const Point &b, const Point &o) {
  66. Point p1 = a - o, p2 = b - o;
  67. return (p1 * p2) / (p1.length() * p2.length());
  68. }
  69.  
  70. struct Circle {
  71. Point c;
  72. double r;
  73. Circle() {}
  74. Circle(Point c, double r): c(c), r(r) {}
  75. void read() {
  76. c.read();
  77. scanf("%lf", &r);
  78. }
  79. bool contain(const Circle &rhs) const {
  80. return sgn(dist(c, rhs.c) + rhs.r - r) <= ;
  81. }
  82. bool contain(const Point &p) const {
  83. return sgn(dist(c, p) - r) <= ;
  84. }
  85. bool intersect(const Circle &rhs) const {
  86. return sgn(dist(c, rhs.c) - r - rhs.r) < ;
  87. }
  88. bool tangency(const Circle &rhs) const {
  89. return sgn(dist(c, rhs.c) - r - rhs.r) == ;
  90. }
  91. };
  92.  
  93. int intersection(const Point &st, const Point &ed, const Circle &cir, Point &p1, Point &p2) {
  94. double angle = cosIncludeAngle(ed, cir.c, st);
  95. if(isnan(angle)) {
  96. Point v = (ed - st) / dist(st, ed);
  97. p1 = cir.c + v * cir.r;
  98. p2 = cir.c - v * cir.r;
  99. return + (cir.r > );
  100. }
  101. double B = dist(cir.c, st);
  102. double a = , b = - * B * angle, c = sqr(B) - sqr(cir.r);
  103. double delta = sqr(b) - * a * c;
  104. if(sgn(delta) < ) return ;
  105. if(sgn(delta) == ) delta = ;
  106. double x1 = (-b - sqrt(delta)) / ( * a), x2 = (-b + sqrt(delta)) / ( * a);
  107. Point v = (ed - st) / dist(ed, st);
  108. p1 = st + v * x1;
  109. p2 = st + v * x2;
  110. return + sgn(delta);
  111. }
  112.  
  113. int intersection(const Circle &c1, const Circle &c2, Point &p1, Point &p2) {
  114. if(c1.contain(c2) || c2.contain(c1)) return ;
  115. if(!c1.intersect(c2) && !c1.tangency(c2)) return ;
  116. double d = dist(c1.c, c2.c);
  117. double d1 = (sqr(c2.r) + sqr(d) - sqr(c1.r)) / / d;
  118. double d2 = sqrt(sqr(c2.r) - sqr(d1));
  119. Point v1 = c2.c + (c1.c - c2.c) / d * d1;
  120. Point v2 = (c1.c - c2.c).rotate() / d;
  121. p1 = v1 + v2 * d2;
  122. p2 = v1 - v2 * d2;
  123. return - (p1 == p2);
  124. }
  125.  
  126. struct Graph {
  127. int head[MAXV], ecnt;
  128. int to[MAXE], next[MAXE];
  129. double cost[MAXE];
  130. int n, st, ed;
  131.  
  132. void init() {
  133. memset(head, -, sizeof(head));
  134. ecnt = ;
  135. }
  136.  
  137. void add_edge(int u, int v, double c) {
  138. to[ecnt] = v; cost[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
  139. to[ecnt] = u; cost[ecnt] = c; next[ecnt] = head[v]; head[v] = ecnt++;
  140. }
  141.  
  142. double dis[MAXV];
  143. bool vis[MAXV];
  144.  
  145. double dijksrta(int st, int ed, int n) {
  146. for(int i = ; i < n; ++i) dis[i] = INF;
  147. dis[st] = ;
  148. memset(vis, , sizeof(vis));
  149. while(true) {
  150. int u = -; double d = INF;
  151. for(int i = ; i < n; ++i) if(!vis[i])
  152. if(dis[i] < d) d = dis[i], u = i;
  153. if(d == INF) break;
  154. vis[u] = true;
  155. for(int p = head[u]; ~p; p = next[p]) {
  156. int &v = to[p];
  157. if(!vis[v]) dis[v] = min(dis[v], dis[u] + cost[p]);
  158. }
  159. }
  160. return dis[ed];
  161. }
  162. } G;
  163.  
  164. Circle cir[MAXN];
  165. int T, n;
  166.  
  167. Point list[MAXV];
  168.  
  169. bool havePath(Point st, Point ed) {
  170. if(ed < st) swap(st, ed);
  171. if(st == ed) return true;
  172. Point p1, p2;
  173. int pcnt = ;
  174. list[pcnt++] = st;
  175. list[pcnt++] = ed;
  176. for(int i = ; i < n; ++i) {
  177. int c = intersection(st, ed, cir[i], p1, p2);
  178. if(c >= ) list[pcnt++] = p1;
  179. if(c >= ) list[pcnt++] = p2;
  180. }
  181. sort(list, list + pcnt);
  182. for(int i = ; i < pcnt; ++i) {
  183. if(list[i] < st || list[i] == st) continue;
  184. bool flag = false;
  185. //Point x = (list[i] + list[i - 1]) / 2;
  186. for(int j = ; j < n && !flag; ++j)
  187. if(cir[j].contain(list[i]) && cir[j].contain(list[i - ])) flag = true;
  188. if(!flag) return false;
  189. if(list[i] == ed) break;
  190. }
  191. return true;
  192. }
  193.  
  194. Point p[MAXV];
  195. int cnt;
  196.  
  197. double solve() {
  198. Point p1, p2;
  199. cnt = ;
  200. p[cnt++] = cir[].c; p[cnt++] = cir[n - ].c;
  201. for(int i = ; i < n; ++i) {
  202. for(int j = i + ; j < n; ++j) {
  203. int c = intersection(cir[i], cir[j], p1, p2);
  204. if(c >= ) p[cnt++] = p1;
  205. if(c >= ) p[cnt++] = p2;
  206. }
  207. }
  208. G.init();
  209. for(int i = ; i < cnt; ++i) {
  210. for(int j = i + ; j < cnt; ++j)
  211. if(havePath(p[i], p[j])) G.add_edge(i, j, dist(p[i], p[j]));
  212. }
  213. return G.dijksrta(, , cnt);
  214. }
  215.  
  216. int main() {
  217. scanf("%d", &T);
  218. for(int kase = ; kase <= T; ++kase) {
  219. scanf("%d", &n);
  220. for(int i = ; i < n; ++i) cir[i].read();
  221. double res = solve();
  222. if(res == INF) printf("Case %d: No such path.\n", kase);
  223. else printf("Case %d: %.4f\n", kase, res);
  224. }
  225. }

HDU 4063 Aircraft(计算几何)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)的更多相关文章

  1. HDU 4069 Squiggly Sudoku(DLX)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4069 Problem Description Today we play a squiggly sud ...

  2. HDU 4064 Carcassonne(插头DP)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4064 Problem Description Carcassonne is a tile-based ...

  3. HDU 4031 Attack(离线+线段树)(The 36th ACM/ICPC Asia Regional Chengdu Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4031 Problem Description Today is the 10th Annual of ...

  4. HDU 4291 A Short problem(2012 ACM/ICPC Asia Regional Chengdu Online)

    HDU 4291 A Short problem(2012 ACM/ICPC Asia Regional Chengdu Online) 题目链接http://acm.hdu.edu.cn/showp ...

  5. 【动态规划】HDU 5492 Find a path (2015 ACM/ICPC Asia Regional Hefei Online)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5492 题目大意: 一个N*M的矩阵,一个人从(1,1)走到(N,M),每次只能向下或向右走.求(N+ ...

  6. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  7. HDU 4758——Walk Through Squares——2013 ACM/ICPC Asia Regional Nanjing Online

    与其说这是一次重温AC自动机+dp,倒不如说这是个坑,而且把队友给深坑了. 这个题目都没A得出来,我只觉得我以前的AC自动机的题目都白刷了——深坑啊. 题目的意思是给你两个串,每个串只含有R或者D,要 ...

  8. Hdu 5459 Jesus Is Here (2015 ACM/ICPC Asia Regional Shenyang Online) 递推

    题目链接: Hdu 5459 Jesus Is Here 题目描述: s1 = 'c', s2 = 'ff', s3 = s1 + s2; 问sn里面所有的字符c的距离是多少? 解题思路: 直觉告诉我 ...

  9. HDU 5010 Get the Nut(2014 ACM/ICPC Asia Regional Xi'an Online)

    思路:广搜, 因为空格加上动物最多只有32个那么对这32个进行编号,就能可以用一个数字来表示状态了,因为只有 ‘P’   'S' 'M' '.' 那么就可以用4进制刚好可以用64位表示. 接下去每次就 ...

随机推荐

  1. Qt中sleep()的实现(耳目一新的两种方法)

    在Qt中并没有Sleep函数可以调用,在程序编写时往往需要休眠几秒,这里举出两个方法,不知道是否啥不良隐患没~~ 方法一: class SleeperThread : public QThread{p ...

  2. Let's Encrypt这个免费的证书签发服务

    使用的是Let's Encrypt这个免费的证书签发服务,按照这里的教程一步步照着来,很快就完成了. 迁移过程总体来说比较顺利,只是遇到了两个不大不小的坑.一个是域名的跳转问题,迁移完成以后对于所有h ...

  3. Windows下 使用CodeBlocks配置OpenGL开发环境

    CodeBlocks版本:13.12 下载OpenGL配置文件 1.glut.dll glut32.dll放入系统盘Windows\System32文件夹 2.glut.h放入CodeBlocks安装 ...

  4. php-- Linux图形界面与字符界面切换

    转自:http://blog.163.com/wang_ly2442/blog/static/9494340720128355054551/ 1. 启动时进入字符界面,后来想切换到图形界面:使用sta ...

  5. 应中DOS中断显示字符串(摘自《汇编语言》王爽)

    data segment s1 db 'Good,better,best,$' s2 db 'Never let it rest,$' s3 db 'Till good is better,$' s4 ...

  6. Swift 遇到的报错信息

    第一个,没看懂.一开始还以为是不支持iOS7的缘故. dyld: Library not loaded: @rpath/libswiftCore.dylib Referenced from: /var ...

  7. angularJs之模块化

    <!DOCTYPE HTML><html ng-app="myApp"><head><meta http-equiv="Cont ...

  8. 破解Mysql数据库密码

    破解Mysql数据库密码 点我,点我,破解mysql数据库密码:

  9. 由单例模式学到:volatile关键字

    MSDN上说: volatile 关键字指示一个字段可以由多个同时执行的线程修改. 声明为 volatile 的字段不受编译器优化的限制. 这样可以确保该字段在任何时间呈现的都是最新的值. volat ...

  10. 面向对象编程(八)——this关键字

    很多人一提起它,就说“当前对象”,可到底什么是当前对象,是什么当前对象,他自己也不清楚. this(隐式参数) 普通方法中,this总是指向当前调用该方法的对象. 构造方法中,this总是指向正要初始 ...