Advertisement
a53

walle

a53
May 7th, 2019
235
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.44 KB | None | 0 0
  1. #include <fstream>
  2. #include <vector>
  3. #include <cassert>
  4. #include <queue>
  5. #include <algorithm>
  6. #include <tuple>
  7. #include <limits>
  8. using namespace std;
  9.  
  10. static const int dx[4] = {-1, 0, 1, 0};
  11. static const int dy[4] = {0, -1, 0, 1};
  12. static const int kInfinite = numeric_limits<int>::max() / 2;
  13.  
  14. vector< vector<int> > get_distances(const vector<string> &board, pair<int, int> start, int plus_time) {
  15. queue< pair<int, int> > normal_queue, plus_queue;
  16. vector< vector<int> > distances(board.size(), vector<int>(board[0].size(), kInfinite));
  17.  
  18. normal_queue.push(start);
  19. distances[start.first][start.second] = 0;
  20.  
  21. while (!normal_queue.empty() || !plus_queue.empty()) {
  22. int x, y;
  23. if (plus_queue.empty()) {
  24. tie(x, y) = normal_queue.front();
  25. normal_queue.pop();
  26. } else if (normal_queue.empty()) {
  27. tie(x, y) = plus_queue.front();
  28. plus_queue.pop();
  29. } else {
  30. int x1, y1, x2, y2;
  31. tie(x1, y1) = normal_queue.front();
  32. tie(x2, y2) = plus_queue.front();
  33. if (distances[x1][y1] <= distances[x2][y2]) {
  34. x = x1;
  35. y = y1;
  36. normal_queue.pop();
  37. } else {
  38. x = x2;
  39. y = y2;
  40. plus_queue.pop();
  41. }
  42. }
  43.  
  44. for (int i = 0; i < 4; ++i) {
  45. int newx = x + dx[i];
  46. int newy = y + dy[i];
  47. if (newx < 0 || newy < 0 || newx >= int(board.size()) || newy >= int(board[0].size()))
  48. continue;
  49. if (distances[newx][newy] == kInfinite) {
  50. distances[newx][newy] = distances[x][y] + 1;
  51. if (board[newx][newy] == '+') {
  52. distances[newx][newy] += plus_time;
  53. plus_queue.emplace(newx, newy);
  54. } else if (board[newx][newy] == '.')
  55. normal_queue.emplace(newx, newy);
  56. }
  57. }
  58. }
  59. return distances;
  60. }
  61.  
  62. int main() {
  63. ifstream cin("walle.in");
  64. ofstream cout("walle.out");
  65.  
  66. int N, M, T;
  67. assert(cin >> N >> M >> T);
  68. assert(1 <= N && N <= 500);
  69. assert(1 <= M && M <= 500);
  70. assert(0 <= T && T <= 1000);
  71. vector<string> board(N);
  72. for (int i = 0; i < N; ++i) {
  73. assert(cin >> board[i]);
  74. for (auto &c : board[i])
  75. assert(c == '.' || c == '+' || c == 'E' || c == 'P' || c == 'W' || c == '#');
  76. }
  77.  
  78. pair<int, int> start(-1, -1), end(-1, -1);
  79. int portals = 0;
  80. for (int i = 0; i < N; ++i)
  81. for (int j = 0; j < M; ++j)
  82. if (board[i][j] == 'W') {
  83. assert(start == make_pair(-1, -1));
  84. start = make_pair(i, j);
  85. } else if (board[i][j] == 'E') {
  86. assert(end == make_pair(-1, -1));
  87. end = make_pair(i, j);
  88. } else if (board[i][j] == 'P')
  89. ++portals;
  90. assert(start != make_pair(-1, -1));
  91. assert(end != make_pair(-1, -1));
  92. assert(portals > 1);
  93.  
  94. auto start_distances = get_distances(board, start, T);
  95. auto end_distances = get_distances(board, end, T);
  96.  
  97. int answer = kInfinite;
  98. // first lets test directly
  99. answer = min(answer, start_distances[end.first][end.second]);
  100.  
  101. // then through a portal, best to know max distance from a portal to the end
  102. // and second max
  103. // and closest to start (we'll need that later)
  104. int max_distance = 0;
  105. int second_max_distance = 0;
  106. int closest = kInfinite;
  107. for (int i = 0; i < N; ++i)
  108. for (int j = 0; j < M; ++j)
  109. if (board[i][j] == 'P') {
  110. if (end_distances[i][j] > max_distance) {
  111. second_max_distance = max_distance;
  112. max_distance = end_distances[i][j];
  113. } else if (end_distances[i][j] > second_max_distance) {
  114. second_max_distance = end_distances[i][j];
  115. }
  116.  
  117. closest = min(closest, start_distances[i][j]);
  118. }
  119. vector< vector<int> > then_to_end(N, vector<int>(M, 0));
  120. for (int i = 0; i < N; ++i)
  121. for (int j = 0; j < M; ++j)
  122. if (board[i][j] == 'P') {
  123. // let's say we hop into this portal
  124. if (end_distances[i][j] == max_distance)
  125. then_to_end[i][j] = second_max_distance;
  126. else
  127. then_to_end[i][j] = max_distance;
  128. answer = min(answer, start_distances[i][j] + then_to_end[i][j]);
  129. }
  130. for (int i = 0; i < N; ++i)
  131. for (int j = 0; j < M; ++j)
  132. if (board[i][j] == 'P') {
  133. if (closest == kInfinite || then_to_end[i][j] == kInfinite)
  134. continue;
  135. int cost_empty = kInfinite;
  136. for (int k = 0; k < 4; ++k) {
  137. int x = i + dx[k];
  138. int y = j + dy[k];
  139. if (x < 0 || y < 0 || x >= N || y >= M)
  140. continue;
  141. if (board[x][y] == '.')
  142. cost_empty = min(cost_empty, 2);
  143. else if (board[x][y] == '+')
  144. cost_empty = min(cost_empty, 2 + T);
  145. }
  146. answer = min(answer, closest + cost_empty + then_to_end[i][j]);
  147. }
  148. if (answer == kInfinite)
  149. answer = -1;
  150. cout << answer <<'\n';
  151. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement