Advertisement
Argent007

Vasya project

Mar 22nd, 2024 (edited)
853
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.80 KB | None | 0 0
  1. // ConsoleApplication1.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
  2. //
  3.  
  4. #include <iostream>
  5. #include <vector>
  6. #include <queue>
  7. #include <algorithm>
  8. #include <map>
  9. #include <fstream>
  10. #include <optional>
  11.  
  12. using namespace std;
  13.  
  14. struct cell
  15. {
  16.     int r, c;
  17.     bool operator<(const cell& rhs)const
  18.     {
  19.         return r < rhs.r || (r == rhs.r && c < rhs.c);
  20.     }
  21.     cell operator+(cell rhs)
  22.     {
  23.         return { r + rhs.r,c + rhs.c };
  24.     }
  25.     bool is_inside(int rows, int cols)
  26.     {
  27.         return 0 <= r && r < rows && 0 <= c && c < cols;
  28.     }
  29. };
  30.  
  31. static vector<cell> directions{ {0,1},{1,0},{-1,0},{0,-1} };
  32. static int infty = 1'000'000;
  33.  
  34. class labyrinth
  35. {
  36.     vector<vector<char>> m;
  37. public:
  38.     labyrinth(size_t rows, size_t cols)
  39.     {
  40.         m.assign(rows, vector<char>(cols, '.'));
  41.     }
  42.     vector<char>& operator[](int row)
  43.     {
  44.         return m[row];
  45.     }
  46.     const vector<char>& operator[](int row) const
  47.     {
  48.         return m[row];
  49.     }
  50.     char& operator()(const cell& C)
  51.     {
  52.         return m[C.r][C.c];
  53.     }
  54.     const char& operator()(const cell& C) const
  55.     {
  56.         return m[C.r][C.c];
  57.     }
  58.     int rows() const
  59.     {
  60.         return m.size();
  61.     }
  62.     int cols() const
  63.     {
  64.         return m.size() == 0 ? 0 : m[0].size();
  65.     }
  66. };
  67.  
  68. labyrinth get_lab_from_stream(istream& inp)
  69. {
  70.     int rows, cols;
  71.     inp >> rows >> cols;
  72.     labyrinth lab(rows, cols);
  73.     for (size_t i = 0; i < rows; i++)
  74.     {
  75.         for (size_t j = 0; j < cols; j++)
  76.         {
  77.             inp >> lab[lab.rows() - i - 1][j];
  78.         }
  79.     }
  80.     return lab;
  81. }
  82.  
  83. void BFS(const labyrinth& lab, cell s, map<cell, double>& d, map<cell, cell>& p, bool requires_init)
  84. {
  85.     if (requires_init)
  86.     {
  87.         for (int i = 0; i < lab.rows(); i++)
  88.             for (int j = 0; j < lab.cols(); j++)
  89.             {
  90.                 d[{i, j}] = infty; //lab.rows() * lab.cols();
  91.                 p[{i, j}] = { -1,-1 };
  92.             }
  93.     }
  94.     d[s] = 0;
  95.     queue<cell> Q;
  96.     Q.push(s);
  97.     while (Q.size())
  98.     {
  99.         auto u = Q.front();
  100.         Q.pop();
  101.         for (auto dir : directions)
  102.         {
  103.             auto v = u + dir;
  104.             if (!v.is_inside(lab.rows(), lab.cols())) continue;
  105.             if (lab(v) != '#' && d[v] > d[u] + 1)
  106.             {
  107.                 d[v] = d[u] + 1;
  108.                 p[v] = u;
  109.                 Q.push(v);
  110.             }
  111.         }
  112.     }
  113. }
  114.  
  115. void BFS(const labyrinth& lab, const vector<cell>& s, map<cell, double>& d, map<cell, cell>& p, bool requires_init)
  116. {
  117.     if (requires_init)
  118.     {
  119.         for (int i = 0; i < lab.rows(); i++)
  120.             for (int j = 0; j < lab.cols(); j++)
  121.             {
  122.                 d[{i, j}] = infty; //lab.rows() * lab.cols();
  123.                 p[{i, j}] = { -1,-1 };
  124.             }
  125.     }
  126.     queue<cell> Q;
  127.     for (auto u : s)
  128.     {
  129.         d[u] = 0;
  130.         Q.push(u);
  131.     }
  132.     while (Q.size())
  133.     {
  134.         auto u = Q.front();
  135.         Q.pop();
  136.         for (auto dir : directions)
  137.         {
  138.             auto v = u + dir;
  139.             if (!v.is_inside(lab.rows(), lab.cols())) continue;
  140.             if (lab(v) != '#' && d[v] > d[u] + 1)
  141.             {
  142.                 d[v] = d[u] + 1;
  143.                 p[v] = u;
  144.                 Q.push(v);
  145.             }
  146.         }
  147.     }
  148. }
  149.  
  150. //Вася и потоп
  151. //flood_speed - интервал затопления очередного уровня
  152. void BFS2(const labyrinth& lab, cell s, double flood_speed, map<cell, double>& d, map<cell, cell>& p, bool requires_init)
  153. {
  154.     if (requires_init)
  155.     {
  156.         for (int i = 0; i < lab.rows(); i++)
  157.             for (int j = 0; j < lab.cols(); j++)
  158.             {
  159.                 d[{i, j}] = infty; //lab.rows() * lab.cols();
  160.                 p[{i, j}] = { -1,-1 };
  161.             }
  162.     }
  163.     d[s] = 0;
  164.     queue<cell> Q;
  165.     Q.push(s);
  166.     while (Q.size())
  167.     {
  168.         auto u = Q.front();
  169.         Q.pop();
  170.         for (auto dir : directions)
  171.         {
  172.             auto v = u + dir;
  173.             if (!v.is_inside(lab.rows(), lab.cols())) continue;
  174.             if (lab(v) != '#' && d[v] > d[u] + 1 && v.r >= floor(d[u] / flood_speed))
  175.             {
  176.                 d[v] = d[u] + 1;
  177.                 p[v] = u;
  178.                 Q.push(v);
  179.             }
  180.         }
  181.     }
  182. }
  183.  
  184. //Вася и потоп
  185. //fire_speed - интервал распространения огня
  186. void BFS3(const labyrinth& lab, cell s, double fire_speed, map<cell, double>& d, map<cell, cell>& p, bool requires_init)
  187. {
  188.     if (requires_init)
  189.     {
  190.         for (int i = 0; i < lab.rows(); i++)
  191.             for (int j = 0; j < lab.cols(); j++)
  192.             {
  193.                 d[{i, j}] = infty; //lab.rows() * lab.cols();
  194.                 p[{i, j}] = { -1,-1 };
  195.             }
  196.     }
  197.     vector<cell> fire_cells;
  198.     for (int i = 0; i < lab.rows(); i++)
  199.         for (int j = 0; j < lab.cols(); j++)
  200.         {
  201.             if (lab[i][j] == '*')
  202.                 fire_cells.push_back({ i,j });
  203.         }
  204.     map<cell, double> dfire;
  205.     map<cell, cell> pfire;
  206.     BFS(lab, fire_cells, dfire, pfire, true);
  207.  
  208.     d[s] = 0;
  209.     queue<cell> Q;
  210.     Q.push(s);
  211.     while (Q.size())
  212.     {
  213.         auto u = Q.front();
  214.         Q.pop();
  215.         for (auto dir : directions)
  216.         {
  217.             auto v = u + dir;
  218.             if (!v.is_inside(lab.rows(), lab.cols())) continue;
  219.             if (lab(v) != '#' && d[v] == infty && dfire[v] * fire_speed > d[u])
  220.             {
  221.                 d[v] = d[u] + 1;
  222.                 p[v] = u;
  223.                 Q.push(v);
  224.             }
  225.         }
  226.     }
  227. }
  228.  
  229. //Вася и слизь
  230. //slime_time - время для перехода из клетки со слизью
  231. void BFS4(const labyrinth& lab, cell s, double slime_time, map<cell, double>& d, map<cell, cell>& p, bool requires_init)
  232. {
  233.     if (requires_init)
  234.     {
  235.         for (int i = 0; i < lab.rows(); i++)
  236.             for (int j = 0; j < lab.cols(); j++)
  237.             {
  238.                 d[{i, j}] = infty; //lab.rows() * lab.cols();
  239.                 p[{i, j}] = { -1,-1 };
  240.             }
  241.     }
  242.     d[s] = 0;
  243.     queue<cell> Q;
  244.     Q.push(s);
  245.     while (Q.size())
  246.     {
  247.         auto u = Q.front();
  248.         Q.pop();
  249.         for (auto dir : directions)
  250.         {
  251.             auto v = u + dir;
  252.             if (!v.is_inside(lab.rows(), lab.cols())) continue;
  253.             if (lab(v) != '#' && (lab(u) != '~' ? d[v] > d[u] + 1 : d[v] > d[u] + slime_time))
  254.             {
  255.                 d[v] = d[u] + (lab(u) != '~' ? 1.0 : slime_time);
  256.                 p[v] = u;
  257.                 Q.push(v);
  258.             }
  259.         }
  260.     }
  261. }
  262.  
  263. //алгоритм поиска в ширину для имитации растекания слизи
  264. void BFS_slime(const labyrinth& lab, const vector<cell>& s, map<cell, double>& d, map<cell, cell>& p, bool requires_init)
  265. {
  266.     if (requires_init)
  267.     {
  268.         for (int i = 0; i < lab.rows(); i++)
  269.             for (int j = 0; j < lab.cols(); j++)
  270.             {
  271.                 d[{i, j}] = infty; //lab.rows() * lab.cols();
  272.                 p[{i, j}] = { -1,-1 };
  273.             }
  274.     }
  275.     queue<cell> Q;
  276.     for (auto u : s)
  277.     {
  278.         d[u] = 0;
  279.         Q.push(u);
  280.     }
  281.     while (Q.size())
  282.     {
  283.         auto u = Q.front();
  284.         Q.pop();
  285.         vector<cell> _directions;
  286.         if (!(u + cell{ -1, 0 }).is_inside(lab.rows(), lab.cols()) || lab(u + cell{ -1, 0 }) != '#')
  287.             _directions.assign({ { 0,-1 },{0,1} });
  288.         else
  289.             _directions.assign({ { -1,0 } });
  290.         for (auto dir : _directions)
  291.         {
  292.             auto v = u + dir;
  293.             if (!v.is_inside(lab.rows(), lab.cols())) continue;
  294.             if (lab(v) != '#' && d[v] > d[u] + 1)
  295.             {
  296.                 d[v] = d[u] + 1;
  297.                 p[v] = u;
  298.                 Q.push(v);
  299.             }
  300.         }
  301.     }
  302. }
  303.  
  304. //Вася и слизь потекла
  305. //slime_time - время для перехода из клетки со слизью
  306. //slime_speed - время для растекания слизи на соседнюю клетку
  307. //слизь либо стекает вниз, если под ней свободная клетка, либо растекается вправо и влево
  308. void BFS5(const labyrinth& lab, cell s, double slime_time, double slime_speed, map<cell, double>& d, map<cell, cell>& p, bool requires_init)
  309. {
  310.     if (requires_init)
  311.     {
  312.         for (int i = 0; i < lab.rows(); i++)
  313.             for (int j = 0; j < lab.cols(); j++)
  314.             {
  315.                 d[{i, j}] = infty; //lab.rows() * lab.cols();
  316.                 p[{i, j}] = { -1,-1 };
  317.             }
  318.     }
  319.     vector<cell> slime_cells;
  320.     for (int i = 0; i < lab.rows(); i++)
  321.         for (int j = 0; j < lab.cols(); j++)
  322.             if (lab[i][j] == '~')
  323.                 slime_cells.push_back({ i,j });
  324.     map<cell, double> dslime;
  325.     map<cell, cell> pslime;
  326.     BFS_slime(lab, slime_cells, dslime, pslime, true);
  327.  
  328.     d[s] = 0;
  329.     queue<cell> Q;
  330.     Q.push(s);
  331.     while (Q.size())
  332.     {
  333.         auto u = Q.front();
  334.         Q.pop();
  335.         for (auto dir : directions)
  336.         {
  337.             auto v = u + dir;
  338.             if (!v.is_inside(lab.rows(), lab.cols())) continue;
  339.             if (lab(v) != '#' && (dslime[u] * slime_speed > d[u] ? d[v] > d[u] + 1 : d[v] > d[u] + slime_time))
  340.             {
  341.                 d[v] = d[u] + (dslime[u] * slime_speed > d[u] ? 1.0 : slime_time);
  342.                 p[v] = u;
  343.                 Q.push(v);
  344.             }
  345.         }
  346.     }
  347. }
  348.  
  349. //Вася и 1 динамамит
  350.  
  351. //Специальная версия поиска в ширину, которая заходит в стены, но не выходит из них
  352. void BFS_wall(const labyrinth& lab, cell s, map<cell, double>& d, map<cell, cell>& p, bool requires_init)
  353. {
  354.     if (requires_init)
  355.     {
  356.         for (int i = 0; i < lab.rows(); i++)
  357.             for (int j = 0; j < lab.cols(); j++)
  358.             {
  359.                 d[{i, j}] = infty; //lab.rows() * lab.cols();
  360.                 p[{i, j}] = { -1,-1 };
  361.             }
  362.     }
  363.     queue<cell> Q;
  364.     d[s] = 0;
  365.     Q.push(s);
  366.     while (Q.size())
  367.     {
  368.         auto u = Q.front();
  369.         Q.pop();
  370.         for (auto dir : directions)
  371.         {
  372.             auto v = u + dir;
  373.             if (!v.is_inside(lab.rows(), lab.cols())) continue;
  374.             if (d[v] > d[u] + 1)
  375.             {
  376.                 d[v] = d[u] + 1;
  377.                 p[v] = u;
  378.                 if(lab(v) != '#')
  379.                     Q.push(v);
  380.             }
  381.         }
  382.     }
  383. }
  384.  
  385. std::optional<cell> optimal_cell_to_explode(const labyrinth& lab, cell start, cell finish)
  386. {
  387.     map<cell, double> ds, df;
  388.     map<cell,cell> ps, pf;
  389.     BFS_wall(lab, start, ds, ps, true);
  390.     BFS_wall(lab, finish, df, pf, true);
  391.     cell opt=start;
  392.     double optlength = ds[start]+df[start];
  393.     for (int i = 0; i < lab.rows(); i++)
  394.     {
  395.         for (int j = 0; j < lab.cols(); j++)
  396.         {
  397.             if (optlength > ds[{i, j}] + df[{i, j}])
  398.             {
  399.                 optlength = ds[{i, j}] + df[{i, j}];
  400.                 opt = { i,j };
  401.             }
  402.         }
  403.     }
  404.     //std::cout << optlength << std::endl;
  405.     //std::cout << ds[{7, 6}] << " " << df[{7, 6}] << std::endl;
  406.     if (optlength == infty)
  407.         return std::nullopt;
  408.     return opt;
  409. }
  410.  
  411. vector<cell> get_path(map<cell, double>& d, map<cell, cell>& p, cell dest)
  412. {
  413.     vector<cell> res;
  414.     if (d[dest] == infty)
  415.         return res;
  416.     res.push_back(dest);
  417.     while (d[res.back()] > 0)
  418.         res.push_back(p[res.back()]);
  419.     reverse(begin(res), end(res));
  420.     return res;
  421. }
  422.  
  423. int main()
  424. {
  425.     fstream inp("lab.txt");
  426.     auto lab = get_lab_from_stream(inp);
  427.     map<cell, double> d;
  428.     map<cell, cell> p;
  429.     auto res=optimal_cell_to_explode(lab, { 0,0 }, {11,11});
  430.     if (res)
  431.         std::cout << res.value().r << " " << res.value().c << std::endl;
  432.     else
  433.         std::cout << "No wall to explode\n";
  434.  
  435.     //std::cout << d[{ lab.rows() - 1, lab.cols() - 1 }] << std::endl;
  436.  
  437.     //auto path = get_path(d, p, { lab.rows() - 1,lab.cols() - 1 });
  438.     //for (auto v : path)
  439.     //    std::cout << '(' << v.r << ',' << v.c << ") ";
  440.  
  441.     std::cout << "\n";
  442. }
  443.  
  444. // Запуск программы: CTRL+F5 или меню "Отладка" > "Запуск без отладки"
  445. // Отладка программы: F5 или меню "Отладка" > "Запустить отладку"
  446.  
  447. // Советы по началу работы
  448. //   1. В окне обозревателя решений можно добавлять файлы и управлять ими.
  449. //   2. В окне Team Explorer можно подключиться к системе управления версиями.
  450. //   3. В окне "Выходные данные" можно просматривать выходные данные сборки и другие сообщения.
  451. //   4. В окне "Список ошибок" можно просматривать ошибки.
  452. //   5. Последовательно выберите пункты меню "Проект" > "Добавить новый элемент", чтобы создать файлы кода, или "Проект" > "Добавить существующий элемент", чтобы добавить в проект существующие файлы кода.
  453. //   6. Чтобы снова открыть этот проект позже, выберите пункты меню "Файл" > "Открыть" > "Проект" и выберите SLN-файл.
  454. /*
  455. 12 12
  456. ...#..#.....
  457. ........###.
  458. .###.##.#.##
  459. ...###..#...
  460. ...#.#.##.#.
  461. #.##.#....#.
  462. ..#..#..###.
  463. .##.........
  464. ..#..######.
  465. #.........#.
  466. #.#####.##..
  467. ......#...#.
  468. */
Advertisement
Comments
Add Comment
Please, Sign In to add comment
Advertisement