leoanjos

kinho

Mar 9th, 2023
761
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.74 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. typedef long long ll;
  6. typedef pair<int, int> ii;
  7.  
  8. const int MAXV = 10000;
  9. const int INF = 1e9;
  10.  
  11. const int dr[4] = { 0, 1, 0, -1 };
  12. const int dc[4] = { 1, 0, -1, 0 };
  13.  
  14. int R, C, S;
  15. vector<int> length;
  16. vector<vector<bool>> isWormhole;
  17. vector<pair<int, int>> wormholes;
  18. vector<vector<int>> grid;
  19. vector<vector<bool>> occupied;
  20.  
  21. mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
  22.  
  23. void read_input(){
  24.     cin >> C >> R >> S;
  25.  
  26.     length.resize(S);
  27.     for(int i = 0; i < S; i++)
  28.         cin >> length[i];
  29.  
  30.     cin.ignore();
  31.  
  32.     vector<string> input(R);
  33.     grid.assign(R, vector<int>(C));
  34.     isWormhole.assign(R, vector<bool>(C, false));
  35.     occupied.assign(R, vector<bool>(C, false));
  36.  
  37.     for(int i = 0; i < R; i++) getline(cin, input[i]);
  38.  
  39.     for(int i = 0; i < R; i++){
  40.         int cnt = 0;
  41.         string number;
  42.         stringstream ss(input[i]);
  43.         while(ss >> number){
  44.             if (number != "*") grid[i][cnt] = stoi(number);
  45.             else grid[i][cnt] = 0, isWormhole[i][cnt] = true, wormholes.emplace_back(i, cnt);
  46.             cnt++;
  47.         }
  48.     }
  49. }
  50.  
  51. ll score(vector<ii> &snake){
  52.     ll ret = 0;
  53.  
  54.     for(int i=0;i< (int) snake.size();i++){
  55.         int x = snake[i].first;
  56.         int y = snake[i].second;
  57.  
  58.         ret += ll(grid[x][y]);
  59.     }
  60.  
  61.     return ret;
  62. }
  63.  
  64. ii get_new_random_pos() {
  65.     int row = uniform_int_distribution<int>(0, R - 1)(rng);
  66.     int col = uniform_int_distribution<int>(0, C - 1)(rng);
  67.     return make_pair(row, col);
  68. }
  69.  
  70. bool valid(ii pos) {
  71.     return !occupied[pos.first][pos.second];
  72. }
  73.  
  74. ii get_new_random_wormhole() {
  75.     int size = wormholes.size();
  76.     return wormholes[uniform_int_distribution<int>(0, size - 1)(rng)];
  77. }
  78.  
  79. void clear_path(vector<ii> &positions) {
  80.     for (auto [row, col]: positions)
  81.         occupied[row][col] = false;
  82. }
  83.  
  84. vector<ii> get_new_random_path(int id) {
  85.     const int max_attempts = 10;
  86.     const double prob_choose = 0.9;
  87.  
  88.     if (uniform_real_distribution<double>(0, 1.0)(rng) > prob_choose)
  89.         return vector<ii>();
  90.  
  91.     int attempts = 0;
  92.     ii initial = get_new_random_pos();
  93.  
  94.     while ((!valid(initial) || isWormhole[initial.first][initial.second]) && attempts < max_attempts)
  95.         initial = get_new_random_pos(), attempts++;
  96.  
  97.     if (!valid(initial) || isWormhole[initial.first][initial.second])
  98.         return vector<ii>();
  99.  
  100.     ii curr = initial;
  101.     vector<ii> positions(1, initial);
  102.     occupied[curr.first][curr.second] = true;
  103.     bool entry = false;
  104.  
  105.     for (int i = 1; i < length[id]; i++) {
  106.         if (isWormhole[curr.first][curr.second] && entry) {
  107.             if ((int) wormholes.size() == 1) {
  108.                 clear_path(positions);
  109.                 return vector<ii>();
  110.             }
  111.  
  112.             ii newPos;
  113.             do newPos = get_new_random_wormhole();
  114.             while (newPos == curr);
  115.  
  116.             positions.push_back(newPos);
  117.             curr = newPos;
  118.             entry = false;
  119.         } else {
  120.             ii newPos;
  121.             int dir, chosen = 0;
  122.  
  123.             do {
  124.                 dir = uniform_int_distribution<int>(0, 3)(rng);
  125.                 newPos = make_pair((curr.first + dr[dir] + R) % R, (curr.second + dc[dir] + C) % C);
  126.                 chosen |= (1 << dir);
  127.             } while (!valid(newPos) && chosen != 15);
  128.  
  129.             if (!valid(newPos)) {
  130.                 clear_path(positions);
  131.                 return vector<ii>();
  132.             }
  133.  
  134.             if (isWormhole[newPos.first][newPos.second]) entry = true;
  135.             else occupied[newPos.first][newPos.second] = true;
  136.  
  137.             positions.push_back(newPos);
  138.             curr = newPos;
  139.         }
  140.     }
  141.  
  142.     if (isWormhole[curr.first][curr.second]) {
  143.         clear_path(positions);
  144.         return vector<ii>();
  145.     }
  146.  
  147.     return positions;
  148. }
  149.  
  150. vector<vector<ii>> get_initial_paths() {
  151.     vector<vector<ii>> paths;
  152.     for (int i = 0; i < S; i++)
  153.         paths.push_back(get_new_random_path(i));
  154.  
  155.     return paths;
  156. }
  157.  
  158. void mark_snake_path(const vector<ii>& snake_path) {
  159.     for(auto& [x, y] : snake_path) {
  160.         if(isWormhole[x][y]) continue;
  161.         occupied[x][y] = true;
  162.     }
  163. }
  164.  
  165. ll solution_score(const vector<vector<ii>>& S) {
  166.     ll ret = 0;
  167.     for(auto snake_path : S) {
  168.         ret += score(snake_path);
  169.     }
  170.     return ret;
  171. }
  172.  
  173. void undo_snake_path(const vector<ii>& snake_path) {
  174.     for(auto& [x, y] : snake_path) {
  175.         if(isWormhole[x][y]) continue;
  176.         occupied[x][y] = false;
  177.     }
  178. }
  179. tuple<int, vector<ii>> get_neighborhood(const vector<vector<ii>>& snakes) {
  180.     int S = (int)snakes.size();
  181.     int id = uniform_int_distribution<int>(0, S - 1)(rng);
  182.     auto new_path = get_new_random_path(id);
  183.     undo_snake_path(snakes[id]);
  184.     undo_snake_path(new_path);
  185.     return make_tuple(id, new_path);
  186. }
  187.  
  188. map<pair<int, int>, char> direction;
  189.  
  190. void init_directions() {
  191.   direction[{1, 0}] = 'D';
  192.   direction[{0, 1}] = 'R';
  193.   direction[{R - 1, 0}] = 'U';
  194.   direction[{0, C - 1}] = 'L';
  195. }
  196.  
  197. void print_solution(const vector<vector<ii>>& S) {
  198.     cout << "#####################\n";
  199.     for(const auto& snake_path : S) {
  200.         if(snake_path.empty()) {
  201.             cout << '\n';
  202.             continue;
  203.         }
  204.         cout << snake_path[0].second << ' ' << snake_path[0].first << ' ';
  205.         int len = (int)snake_path.size();
  206.         for(int i = 1; i < len; ++i) {
  207.             int dx = (snake_path[i].first - snake_path[i - 1].first + R) % R;
  208.             int dy = (snake_path[i].second - snake_path[i - 1].second + C) % C;
  209.  
  210.             if (isWormhole[snake_path[i].first][snake_path[i].second]) {
  211.                 if (isWormhole[snake_path[i - 1].first][snake_path[i - 1].second]) {
  212.                     cout << snake_path[i].second << " " << snake_path[i].first;
  213.                     continue;
  214.                 }
  215.             }
  216.  
  217.             cout << direction[{dx, dy}] << ' ';
  218.         }
  219.         cout << '\n';
  220.     }
  221.     cout << "#####################\n";
  222. }
  223.  
  224. void sAnnealing(){
  225.     // pseudo-code
  226.     /************* setar isso aqui inicialmente
  227.     S0 = estado inicial
  228.     M = numero maximo de iteracoes
  229.     P = pertubacoes por iteracao
  230.     L = numero maximo de sucessos por iteracoes
  231.     alpha = fator de reducao da temperatura
  232.     ******************************************/
  233.     double TEMP_INICIAL = 1000.0;
  234.     double alpha = 0.995;
  235.     int M = 10000;
  236.     int P = 100;
  237.     int print_per_iterations = M / 10;
  238.     double barreira = 1e-8;
  239.  
  240.     vector<vector<ii>> S = get_initial_paths();
  241.     ll total_score = solution_score(S);
  242.     double T0 = TEMP_INICIAL;
  243.     double T = T0;
  244.  
  245.     for(int i=0;i<=M;i++){
  246.         for(int j=0;j<=P;j++){
  247.             auto [snake_id, new_path] = get_neighborhood(S);
  248.  
  249.             ll delta = score(S[snake_id]) - score(new_path);
  250.  
  251.             // energia negativa -> melhor solucao
  252.             if(delta <= 0.0 || exp(-delta/T) > uniform_real_distribution<double>(0, 1.0)(rng)){
  253.                 mark_snake_path(new_path);
  254.                 S[snake_id].swap(new_path);
  255.                 total_score -= delta;
  256.             } else {
  257.                 mark_snake_path(S[snake_id]);
  258.             }
  259.         }
  260.         T = T*alpha;
  261.         if (T < barreira) {
  262.             print_solution(S);
  263.             break;
  264.         }
  265.  
  266.         cerr << "----------------------------------------------------" << '\n';
  267.         cerr << "total_score: " << total_score << '\n';
  268.         cerr << "temperatura: " << T << '\n';
  269.         cerr << "iteracoes: " << i << "/" << M << "\n";
  270.  
  271.         if (i % print_per_iterations == 0)
  272.             print_solution(S);
  273.     }
  274. }
  275.  
  276. int main(){
  277.     ios::sync_with_stdio(0);
  278.     cin.tie(0);
  279.  
  280.     read_input();
  281.     init_directions();
  282.     sAnnealing();
  283. }
Advertisement
Add Comment
Please, Sign In to add comment