Advertisement
stgatilov

Untitled

Nov 3rd, 2019
209
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.12 KB | None | 0 0
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. #include <map>
  5. #include <array>
  6. #include <cassert>
  7. #include <cstdlib>
  8.  
  9. #define all(x) (x).begin(), (x).end()
  10. #define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
  11. #define mp make_pair
  12.  
  13. using namespace std;
  14.  
  15. using ll = long long;
  16. using ld = long double;
  17.  
  18. inline int nxt() {
  19.     int x;
  20.     cin >> x;
  21.     return x;
  22. }
  23.  
  24. using uchar = unsigned char;
  25. const uchar m1 = -1;
  26.  
  27. const int N = 1 << 18;
  28. uchar dp[18][18][N][2];
  29.  
  30. void remax(uchar& x, uchar y) {
  31.     if (x == m1 || x < y) {
  32.         x = y;
  33.     }
  34. }
  35.  
  36. int main()
  37. {
  38.     ios_base::sync_with_stdio(false);
  39.    
  40.     int n = nxt(), m = nxt();
  41.     vector<string> a(n);
  42.     for (int i = 0; i < n; ++i) {
  43.         cin >> a[i];
  44.     }
  45.  
  46.     if (n == 1) {
  47.         if (a[0][0] == 'X') {
  48.             cout << "-1\n";
  49.             return 0;
  50.         }
  51.         int left_x = m;
  52.         for (int i = 0; i < m; ++i) {
  53.             if (a[0][i] == 'X') {
  54.                 left_x = i;
  55.                 break;
  56.             }
  57.         }
  58.         for (int i = left_x; i < m; ++i) {
  59.             if (a[0][i] == '.') {
  60.                 cout << "-1\n";
  61.                 return 0;
  62.             }
  63.         }
  64.         cout << left_x << "\n" << string(left_x, '.') << string(m - left_x, 'X') << "\n";
  65.         return 0;
  66.     }
  67.  
  68.     memset(dp, -1, sizeof(dp));
  69.  
  70.     const int nn = 1 << n;
  71.     for (int mask = 0; mask < nn; ++mask) {
  72.         bool contradiction = false;
  73.         for (int i = 0; i < n; ++i) {
  74.             if (a[i][m - 1] != '?' && !!(mask & (1 << i)) != (a[i][m - 1] == 'X')) {
  75.                 contradiction = true;
  76.                 break;
  77.             }
  78.         }
  79.         if (!contradiction) {
  80.             dp[n - 1][m - 1][mask][0] = 0;
  81.         }
  82.     }
  83.  
  84.     for (int j = m - 1; j >= 0; --j) {
  85.         for (int i = n - 1; i >= 0; --i) {
  86.             int ni = i - 1, nj = j;
  87.             if (ni < 0) {
  88.                 ni = n - 1;
  89.                 nj -= 1;
  90.             }
  91.             if (nj < 0) {
  92.                 break;
  93.             }
  94.             for (int mask = 0; mask < nn; ++mask) {
  95.                 for (bool ok : {false, true}) {
  96.                     if (dp[i][j][mask][ok] == m1) {
  97.                         continue;
  98.                     }
  99.  
  100.                     //cerr << "dp[" << i << "][" << j << "][" << mask << "][" << ok << "] = " << (int)dp[i][j][mask][ok] << "\n";
  101.  
  102.                     int cur = !!(mask & (1 << i));
  103.                     //cerr << "cur is " << cur << "\n";
  104.                     int left = j ? (a[i][j - 1] == '?' ? -1 : a[i][j - 1] == 'X') : 1;
  105.                     //cerr << "left is " << left << "\n";
  106.                     if (cur) {
  107.                         // wall
  108.                         if (left != 1) {
  109.                             int down = (i == n - 1) ? 1 : !!(mask & (1 << (i + 1)));
  110.                             if (!down || !cur) {
  111.                                 //cerr << "remaxing dp[" << ni << "][" << nj << "][" << (mask & (~(1 << i))) << "][" << ok << "] by a wall\n";
  112.                                 remax(dp[ni][nj][mask & (~(1 << i))][ok], dp[i][j][mask][ok]);
  113.                             }
  114.                         }
  115.                         if (left != 0) {
  116.                             //cerr << "remaxing dp[" << ni << "][" << nj << "][" << (mask | (1 << i)) << "][" << ok << "] by a wall\n";
  117.                             remax(dp[ni][nj][mask | (1 << i)][ok], dp[i][j][mask][ok]);
  118.                         }
  119.                     }
  120.                     else {
  121.                         // free cell
  122.                         bool nok = ok || (i == n - 1) || (j == m - 1);
  123.                         int up = i ? !!(mask & (1 << (i - 1))) : 1;
  124.                         int need_left = up ^ 1;
  125.                         if (left > -1 && left != need_left) {
  126.                             continue;
  127.                         }
  128.                         //cerr << "remaxing dp[" << ni << "][" << nj << "][" << ((mask & (~(1 << i))) | (need_left << i)) << "][" << nok << "] by a free cell\n";
  129.                         remax(dp[ni][nj][(mask & (~(1 << i))) | (need_left << i)][nok], dp[i][j][mask][ok] + 1);
  130.                     }
  131.                 }
  132.             }
  133.         }
  134.     }
  135.  
  136.     int ans = dp[0][0][nn - 2][true];
  137.     int x = 0, y = 0, mask = nn - 2;
  138.     bool ok = true;
  139.     if (ans == m1) {
  140.         ans = -1;
  141.     }
  142.     if ((n == 1 || m == 1) && dp[0][0][nn - 2][0] != m1) {
  143.         if (ans == -1 || ans < dp[0][0][nn - 2][0]) {
  144.             ok = false;
  145.             ans = max(ans, (int)dp[0][0][nn - 2][0]);
  146.         }
  147.     }
  148.     if (ans > -1) {
  149.         ans += 1;
  150.     }
  151.  
  152.     cout << ans << "\n";
  153.     if (ans < 0) {
  154.         return 0;
  155.     }
  156.  
  157.     a[0][0] = '.';
  158.  
  159.     uchar cans = ans - 1;
  160.     while (y < m) {
  161.         int nx = x + 1, ny = y;
  162.         if (nx == n) {
  163.             nx = 0;
  164.             ++ny;
  165.         }
  166.         if (ny >= m) {
  167.             break;
  168.         }
  169.  
  170.         int cand_mask = -1;
  171.         bool cand_ok = false;
  172.         uchar cand_ans = m1;
  173.  
  174.         for (int nval : {0, 1}) {
  175.             for (int nok : {0, 1}) {
  176.                 int nmask = (mask & (~(1 << nx))) | (nval << nx);
  177.                 if (dp[nx][ny][nmask][nok] == m1) {
  178.                     continue;
  179.                 }
  180.  
  181.                 if (nval) {
  182.                     // wall
  183.                     int down = (nx == n - 1) ? 1 : !!(nmask & (1 << (nx + 1)));
  184.                     if (!down || !nval)
  185.                     if (dp[nx][ny][nmask][nok] != m1 && dp[nx][ny][nmask][nok] == cans) {
  186.                         cand_mask = nmask;
  187.                         cand_ok = nok;
  188.                         cand_ans = cans;
  189.                         //cerr << "ok a[" << nx << "][" << ny << "] is X\n";
  190.                         a[nx][ny] = 'X';
  191.                         break;
  192.                     }
  193.                 }
  194.                 else {
  195.                     // free cell
  196.                     bool reok = ok || (nx == n - 1) || (ny == m - 1);
  197.                     int up = nx ? !!(nmask & (1 << (nx - 1))) : 1;
  198.                     int need_left = up ^ 1;
  199.                     int left = !!(mask & (1 << nx));
  200.                     if (left != need_left) {
  201.                         continue;
  202.                     }
  203.                     if (dp[nx][ny][nmask][nok] != m1 && dp[nx][ny][nmask][nok] + 1 == cans) {
  204.                         cand_mask = nmask;
  205.                         cand_ok = nok;
  206.                         cand_ans = dp[nx][ny][nmask][nok];
  207.                         //cerr << "ok a[" << nx << "][" << ny << "] is .\n";
  208.                         a[nx][ny] = '.';
  209.                         break;
  210.                     }
  211.                 }
  212.             }
  213.         }
  214.  
  215.         assert(cand_mask > -1);
  216.         mask = cand_mask;
  217.         ok = cand_ok;
  218.         cans = cand_ans;
  219.  
  220.         x = nx;
  221.         y = ny;
  222.     }
  223.  
  224.     for (int i = 0; i < n; ++i) {
  225.         cout << a[i] << "\n";
  226.     }
  227.  
  228.     return 0;
  229. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement