[关闭]
@ZCDHJ 2018-09-27T06:34:32.000000Z 字数 1451 阅读 510

NOIp2018模拟赛 Maze

二分答案 最短路


题面

有一个 n*m 的迷宫,这个迷宫由 n 行 m 列 0 或 1 组成,0 表示可以走,1 表示不能走。
你从起点出发,每次可以向上下左右四个方向走一格,走一格用时 1 秒。
你有一个机器,使得每次在上下移动一步时,用时为 k 秒。
你需要选定一个 k,使得从起点到终点的最短用时等于 s。

我考场上竟然没有写挂,感动

发现最短用时是随着 k 递增的,遂二分 k

然后最短路判断一下就行啦

  1. #include <bits/stdc++.h>
  2. const double EPS = 1e-5;
  3. const int INF = 0x3f3f3f3f;
  4. const int MAXN = 100;
  5. const int NXT[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
  6. int n, m, sx, sy, ex, ey;
  7. int g[MAXN + 5][MAXN + 5];
  8. double s;
  9. double dist[MAXN + 5][MAXN + 5];
  10. struct Heap {
  11. int x, y;
  12. double d;
  13. Heap(){}
  14. Heap(int xx, int yy, double dd) {
  15. x = xx;
  16. y = yy;
  17. d = dd;
  18. }
  19. };
  20. bool operator < (const Heap &a, const Heap &b) {
  21. return a.d > b.d;
  22. }
  23. inline int read() {
  24. register int x = 0;
  25. register char ch = getchar();
  26. while(!isdigit(ch)) ch = getchar();
  27. while(isdigit(ch)) {
  28. x = x * 10 + ch - '0';
  29. ch = getchar();
  30. }
  31. return x;
  32. }
  33. bool check(double x) {
  34. std::priority_queue <Heap> q;
  35. while(!q.empty()) q.pop();
  36. for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) dist[i][j] = INF;
  37. dist[sx][sy] = 0;
  38. q.push(Heap(sx, sy, 0));
  39. while(!q.empty()) {
  40. Heap from = q.top();
  41. q.pop();
  42. if(from.x == ex && from.y == ey) break;
  43. if(from.d != dist[from.x][from.y]) continue;
  44. for(int k = 0; k < 4; ++k) {
  45. int tx = from.x + NXT[k][0], ty = from.y + NXT[k][1];
  46. double w = (k > 1) ? x : 1;
  47. if(g[tx][ty] > 0) continue;
  48. if(dist[tx][ty] > dist[from.x][from.y] + w) {
  49. dist[tx][ty] = dist[from.x][from.y] + w;
  50. q.push(Heap(tx, ty, dist[tx][ty]));
  51. }
  52. }
  53. }
  54. return dist[ex][ey] <= s;
  55. }
  56. int main() {
  57. n = read();
  58. m = read();
  59. sx = read();
  60. sy = read();
  61. ex = read();
  62. ey = read();
  63. for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) g[i][j] = read();
  64. scanf("%lf", &s);
  65. double ans = 0, l = 0, r = s, mid;
  66. while(l + EPS <= r) {
  67. mid = (l + r) / 2;
  68. if(check(mid)) {
  69. l = mid;
  70. ans = mid;
  71. }
  72. else r = mid;
  73. }
  74. printf("%.3lf", ans);
  75. return 0;
  76. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注