Advertisement
KinDeR___

VK профильное задание

Jan 15th, 2025 (edited)
44
0
360 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.52 KB | None | 0 0
  1. /*
  2.     N - количество вершин в графе, M - количество рёбер в графе.
  3.     В нашем случае N = sizeI * sizeJ, M = 2 * sizeI * sizeJ;
  4.  
  5.     Стандартная задача на поиск кратчайшего пути в лабиринте с восстановлением ответа, изначально хотел
  6.     написать Дейкстру за O(NlogM) --> O(sizeI*sizeJ * log(sizeI * sizeJ)), но обратил внимание на
  7.     маленькое ограничения веса ребра,поэтому предположил, что может существовать что-то быстрее Дейкстры.
  8.     Погугля нашёл на codeforces блог про алгоритм 1-K BFS, который работает для графов с весом рёбер от 1 до K.
  9.  
  10.     Блог на codeforces: https://codeforces.net/blog/entry/88408?locale=ru&mobile=true
  11.  
  12.     1-K BFS. Алгоритм работает за O(9 * N + M) --> O(sizeI * sizeJ) по времени и по памяти.
  13. */
  14.  
  15. #include<bits/stdc++.h>
  16.  
  17. using namespace std;
  18.  
  19. const int INF = 1e9;
  20.  
  21. int main() {
  22.     ios::sync_with_stdio(false); // для ускорения ввода и вывода
  23.     cin.tie(nullptr);
  24.  
  25.     freopen("input.txt", "r", stdin);
  26.     freopen("output.txt", "w", stdout);
  27.  
  28.     int sizeI, sizeJ; cin >> sizeI >> sizeJ;
  29.     cin.ignore();
  30.  
  31.     if(sizeI <= 0 || sizeJ <= 0){
  32.         cerr << "Введены отрицательные или равные нулю размеры лабиринта";
  33.         return 1; //возвращаю 1, что в этом случае аналогично вызову exit(1)
  34.     }
  35.  
  36.     if(1LL * sizeI * sizeJ > 1'000'000LL){
  37.         cerr << "Размер лабиринта слишком большой, не можем выделить столько памяти под массив";
  38.         return 1;
  39.     }
  40.  
  41.     vector<vector<int>> field(1 + sizeI + 1, vector<int>(1 + sizeJ + 1, 0));
  42.    
  43.     for(int i = 1; i <= sizeI; i++){
  44.         string s; getline(cin, s);
  45.  
  46.         if(s.size() != sizeJ + sizeJ - 1){
  47.             cerr << "Неправильный ввод данных в клетки лабиринта";
  48.             return 1;
  49.         }
  50.  
  51.         for(int ii = 0, j = 1; ii < s.size(); ii++){
  52.             if(ii % 2 == 0){
  53.                 if('0' <= s[ii] && s[ii] <= '9'){
  54.                     field[i][j] = s[ii] - '0';
  55.                     j++;
  56.                 } else {
  57.                     cerr << "Неправильный ввод данных в клетки лабиринта";
  58.                     return 1;
  59.                 }
  60.             } else if(s[ii] != ' '){
  61.                     cerr << "Неправильный ввод данных в клетки лабиринта";
  62.                     return 1;
  63.             }
  64.         }
  65.        
  66.     }
  67.  
  68.     int startI, startJ, finishI, finishJ;
  69.     cin >> startI >> startJ >> finishI >> finishJ;
  70.  
  71.     startI++, startJ++, finishI++, finishJ++;
  72.  
  73.     if( startI < 1 || startJ > sizeJ || 1 > finishI || finishJ > sizeJ){
  74.         cerr << "Коордианты клетки выходят за границы лабиринта";
  75.         return 1;
  76.     }
  77.  
  78.     if(field[startI][startJ] == 0){
  79.         cerr << "Начальная точка находится в клетке со стеной";
  80.         return 1;
  81.     }
  82.  
  83.     if(field[finishI][finishJ] == 0){
  84.         cerr << "Конечная точка находится в клетке со стеной";
  85.         return 1;
  86.     }
  87.  
  88.     vector<vector<char>> was(1 + sizeI + 1, vector<char>(1 + sizeJ + 1, 0));
  89.     vector<vector<int>> dist(1 + sizeI + 1, vector<int>(1 + sizeJ + 1, INF));
  90.  
  91.     vector<queue<pair<int,int>>> q(10);
  92.     q[0].push({startI, startJ});
  93.     dist[startI][startJ] = field[startI][startJ];
  94.  
  95.     int szQueue = 1, curIndex = 0;
  96.  
  97.     while(szQueue > 0){
  98.         while(q[curIndex % 10].empty()){
  99.             curIndex++;
  100.         }
  101.  
  102.         auto x = q[curIndex % 10].front();
  103.         q[curIndex % 10].pop();
  104.         szQueue--;
  105.  
  106.         int i = x.first, j = x.second;
  107.         if(was[i][j]){
  108.             continue;
  109.         }
  110.  
  111.         was[i][j] = 1;
  112.  
  113.         for(int di = -1; di <= 1; di++){
  114.             for(int dj = -1; dj <= 1; dj++){
  115.                 int ni = i + di, nj = j + dj;
  116.                 if(di * di + dj * dj == 1 && field[ni][nj] > 0 && dist[i][j] + field[ni][nj] < dist[ni][nj]){
  117.                     dist[ni][nj] = dist[i][j] + field[ni][nj];
  118.                     q[dist[ni][nj] % 10].push({ni, nj});
  119.                     szQueue++;
  120.                 }
  121.             }
  122.         }
  123.     }
  124.  
  125.     vector<pair<int,int>> ans;
  126.    
  127.     int curI = finishI, curJ = finishJ;
  128.     while(curI != startI || curJ != startJ){
  129.         ans.push_back({curI, curJ});
  130.  
  131.         bool flag = true;
  132.         for(int di = -1; di <= 1 && flag; di++){
  133.             for(int dj = -1; dj <= 1; dj++){
  134.                 int prevI = curI + di, prevJ = curJ + dj;
  135.                 if(di * di + dj * dj == 1 && field[prevI][prevJ] > 0 && dist[prevI][prevJ] + field[curI][curJ] == dist[curI][curJ]){
  136.                     curI = prevI, curJ = prevJ;
  137.                     flag = false;
  138.                     break;
  139.                 }
  140.             }
  141.         }
  142.     }
  143.  
  144.     ans.push_back({curI, curJ});
  145.     reverse(ans.begin(), ans.end());
  146.  
  147.     for(int i = 0; i < ans.size(); i++){
  148.         cout << ans[i].first - 1 << ' ' << ans[i].second - 1 << '\n';
  149.     }
  150.     cout << '.';
  151.  
  152.     return 0;  
  153. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement