Advertisement
Guest User

Untitled

a guest
Jun 22nd, 2024
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.75 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. #include <queue>
  5. #include <chrono>
  6.  
  7. using namespace std;
  8.  
  9.  
  10. enum Direction {
  11.   kRight = 0,
  12.   kUp = 1,
  13.   kLeft = 2,
  14.   kDown = 3
  15. };
  16.  
  17.  
  18. const char kDirToChar[4] = {'>', '^', '<', 'V'};
  19.  
  20. char ToChar(Direction d) {
  21.     return kDirToChar[d];
  22. }
  23.  
  24. class Maze {
  25. public:
  26.     /*
  27.        `map` - map of the labirinth. '#' indicates a wall. 'E' indicates exit.
  28.     */
  29.     Maze(vector<string> map);
  30.  
  31.     int Width() const; 
  32.     int Height() const;
  33.     bool IsExit(int x, int y) const;
  34.     bool IsWall(int x, int y) const;
  35.  
  36.     /*
  37.        Finds the shortest sequence of moves to get from (x, y) to exit.
  38.        `x` - 0 based column coordinate;
  39.        `y` - 0 based row coordinate;
  40.        (0, 0) is top-left.
  41.     */
  42.     vector<Direction> GetPath(int x, int y) const;
  43.  
  44.     /*
  45.        Moves turtle from position (x,y) according to `commands`.
  46.        `x` - 0 based column coordinate;
  47.        `y` - 0 based row coordinate;
  48.        returns new position in `x` and `y`.
  49.     */
  50.     void ApplyCommands(int &x, int &y, const vector<Direction> &commands) const;
  51.  
  52.     ~Maze() = default;
  53.  
  54. private:
  55.     string _map;
  56.     int _height;
  57.     int _width;
  58.     int _exit;
  59.     int _offset[4];
  60.     vector<int> _prev;
  61.     void Bfs();
  62. };
  63.  
  64.  
  65.  
  66. Maze::Maze(vector<string> map) : _height(map.size()), _width(map[0].size()) {
  67.     for (int i = 0; i < _width + 2; ++i)
  68.         _map += '#';
  69.     for (int i = 0; i < _height; ++i) {
  70.         _map +='#';
  71.         _map += map[i];
  72.         _map += '#';
  73.     }      
  74.     for (int i = 0; i < _width + 2; ++i)
  75.         _map += '#';
  76.     _height += 2;
  77.     _width += 2;
  78.     _offset[kRight] = 1;
  79.     _offset[kUp] = -_width;
  80.     _offset[kLeft] = -1;
  81.     _offset[kDown] = _width;
  82.     for (size_t i = 0; i < _map.size(); ++i) {
  83.         if (_map[i] == 'E') {
  84.           _exit = i;
  85.           break;
  86.         }  
  87.     }
  88.     Bfs();
  89. }
  90.  
  91. void Maze::Bfs() {
  92.     _prev.resize(_map.size(), -1);
  93.     queue<int> q;
  94.     q.push(_exit);
  95.     _prev[_exit] = 0;
  96.     while (!q.empty()) {
  97.         int cur = q.front();
  98.         q.pop();
  99.         for (int k = 0; k < 4; ++k) {
  100.             int npos = cur + _offset[k];
  101.             if (_map[npos] != '#' && _prev[npos] == -1) {
  102.                 _prev[npos] = k^2;
  103.                 q.push(npos);
  104.             }
  105.         }
  106.     }
  107.  
  108.     cout << "Paths in the maze:\n";
  109.     for (int i = 0; i < _height; ++i) {
  110.         for (int j = 0; j < _width; ++j) {
  111.             int cur = i*_width + j;
  112.             if (_map[cur] == '#') {
  113.                 cout << '#';
  114.             } else if (_map[cur] == 'E'){
  115.                 cout << 'E';
  116.             } else {
  117.                 cout << ToChar(Direction(_prev[cur]));
  118.             }
  119.         }
  120.         cout << "\n";
  121.     }
  122.  
  123. }
  124.  
  125. int Maze::Width() const {
  126.     return _width-2;
  127. }
  128.  
  129. int Maze::Height() const {
  130.     return _height-2;
  131. }
  132.  
  133.  
  134. bool Maze::IsExit(int x, int y) const {
  135.     return _map[(y+1)*_width + x + 1] == 'E';
  136. }
  137.  
  138. bool Maze::IsWall(int x, int y) const {
  139.     return _map[(y+1)*_width + x + 1] == '#';
  140. }
  141.  
  142.  
  143. vector<Direction> Maze::GetPath(int x, int y) const {
  144.     int pos = (y+1)*_width + x + 1;
  145.     vector<Direction> commands;
  146.     while (pos != _exit) {
  147.         commands.push_back(Direction(_prev[pos]));
  148.         pos += _offset[_prev[pos]];
  149.     }
  150.     return commands;
  151.  
  152. }
  153.  
  154. void Maze::ApplyCommands(int &x, int &y, const vector<Direction> &commands) const {
  155.     int pos = (y+1)*_width + x + 1;
  156.     for (auto &c : commands) {
  157.         if (pos == _exit) break;
  158.         int npos = pos + _offset[c];
  159.         if (_map[npos] != '#')
  160.             pos = npos;
  161.     }
  162.     y = pos / _width - 1;
  163.     x = pos % _width - 1;
  164. }
  165.  
  166.  
  167.  
  168. vector<string> kMaze1 = {
  169.     "....",
  170.     ".##.",
  171.     "..#.",
  172.     "#E#."
  173. };
  174.  
  175. vector<string> kMaze2 = {
  176.     "....#.....",
  177.     ".##...#.#.",
  178.     "..#####.#.",
  179.     "#E#...#.#.",
  180.     "###.#.....",
  181. };
  182.  
  183. vector<string> kMaze3 = {
  184.     "...................................................",
  185.     "...................................................",
  186.     "...................................................",
  187.     "...................................................",
  188.     "...................................................",
  189.     "...................................................",
  190.     "...................................................",
  191.     "...................................................",
  192.     "...................................................",
  193.     "...................................................",
  194.     "...................................................",
  195.     "...................................................",
  196.     "...................................................",
  197.     "...................................................",
  198.     "...................................................",
  199.     "...................................................",
  200.     "...................................................",
  201.     "E.................................................."
  202. };
  203.  
  204.  
  205.  
  206. bool Check(const Maze &m, const vector<Direction> commands) {
  207.     for (int x = 0; x < m.Width(); ++x) {
  208.         for (int y = 0; y < m.Height(); ++y) {
  209.             if (m.IsWall(x, y)) continue;
  210.             int nx = x;
  211.             int ny = y;
  212.             m.ApplyCommands(nx, ny, commands);
  213.             if (!m.IsExit(nx, ny)) {
  214.                 return false;
  215.             }
  216.         }
  217.     }
  218.     return true;
  219. }
  220.  
  221.  
  222.  
  223. void Algo1(const Maze &m) {
  224.     vector<Direction> commands;
  225.     for (int x = 0; x < m.Width(); ++x) {
  226.         for (int y = 0; y < m.Height(); ++y) {
  227.             if (m.IsWall(x, y)) continue;
  228.             int nx = x;
  229.             int ny = y;
  230.            
  231.             m.ApplyCommands(nx, ny, commands);
  232.             auto c = m.GetPath(nx, ny);
  233.             commands.insert(commands.end(), c.begin(), c.end());
  234.         }
  235.     }
  236.  
  237.     if (!Check(m, commands)) {
  238.         cout << "Botva!\n";
  239.     }
  240.  
  241. }
  242.  
  243.  
  244. void Algo2(const Maze &m) {
  245.     vector<Direction> commands;
  246.  
  247.     vector<pair<int, int>> turtles;
  248.     for (int x = 0; x < m.Width(); ++x) {
  249.         for (int y = 0; y < m.Height(); ++y) {
  250.             if (m.IsWall(x, y)) continue;
  251.             turtles.emplace_back(x, y);
  252.         }
  253.     }
  254.  
  255.     vector<vector<int>> was(m.Width(), vector<int>(m.Height()));
  256.     int stage = 0;
  257.  
  258.     while (!turtles.empty()) {
  259.         auto t = turtles[0];
  260.         auto c = m.GetPath(t.first, t.second);
  261.         commands.insert(commands.end(), c.begin(), c.end());
  262.  
  263.         ++stage;
  264.         size_t last_pos = 0;
  265.         for (size_t i = 1; i < turtles.size(); ++i) {
  266.             m.ApplyCommands(turtles[i].first, turtles[i].second, c);
  267.             if (!m.IsExit(turtles[i].first, turtles[i].second) && was[turtles[i].first][turtles[i].second] < stage) {
  268.                 was[turtles[i].first][turtles[i].second] = stage;
  269.                 turtles[last_pos++] = turtles[i];
  270.             }
  271.         }
  272.         turtles.resize(last_pos);
  273.     }
  274.  
  275.     if (!Check(m, commands)) {
  276.         cout << "Botva!\n";
  277.     }
  278. }
  279.  
  280.  
  281.  
  282. int main() {
  283.     Maze m(kMaze3);
  284.    
  285.     auto start = chrono::high_resolution_clock::now(); 
  286.     for (int i = 0; i < 1000; ++i) {
  287.         Algo2(m);
  288.     }
  289.     auto stop = chrono::high_resolution_clock::now();
  290.     auto duration = chrono::duration_cast<chrono::microseconds>(stop - start);
  291.     cout << "Clever algo took " << duration.count() << "ns\n";
  292.  
  293.     start = chrono::high_resolution_clock::now();  
  294.     for (int i = 0; i < 1000; ++i) {
  295.         Algo1(m);
  296.     }
  297.     stop = chrono::high_resolution_clock::now();
  298.     duration = chrono::duration_cast<chrono::microseconds>(stop - start);
  299.     cout << "Naive algo took " << duration.count() << "ns\n";
  300.     return 0;
  301. }
  302.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement