Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <algorithm>
- #include <vector>
- #include <map>
- #include <array>
- #include <cassert>
- #include <cstdlib>
- #define all(x) (x).begin(), (x).end()
- #define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
- #define mp make_pair
- using namespace std;
- using ll = long long;
- using ld = long double;
- inline int nxt() {
- int x;
- cin >> x;
- return x;
- }
- using uchar = unsigned char;
- const uchar m1 = -1;
- const int N = 1 << 18;
- uchar dp[18][18][N][2];
- void remax(uchar& x, uchar y) {
- if (x == m1 || x < y) {
- x = y;
- }
- }
- int main()
- {
- ios_base::sync_with_stdio(false);
- int n = nxt(), m = nxt();
- vector<string> a(n);
- for (int i = 0; i < n; ++i) {
- cin >> a[i];
- }
- if (n == 1) {
- if (a[0][0] == 'X') {
- cout << "-1\n";
- return 0;
- }
- int left_x = m;
- for (int i = 0; i < m; ++i) {
- if (a[0][i] == 'X') {
- left_x = i;
- break;
- }
- }
- for (int i = left_x; i < m; ++i) {
- if (a[0][i] == '.') {
- cout << "-1\n";
- return 0;
- }
- }
- cout << left_x << "\n" << string(left_x, '.') << string(m - left_x, 'X') << "\n";
- return 0;
- }
- memset(dp, -1, sizeof(dp));
- const int nn = 1 << n;
- for (int mask = 0; mask < nn; ++mask) {
- bool contradiction = false;
- for (int i = 0; i < n; ++i) {
- if (a[i][m - 1] != '?' && !!(mask & (1 << i)) != (a[i][m - 1] == 'X')) {
- contradiction = true;
- break;
- }
- }
- if (!contradiction) {
- dp[n - 1][m - 1][mask][0] = 0;
- }
- }
- for (int j = m - 1; j >= 0; --j) {
- for (int i = n - 1; i >= 0; --i) {
- int ni = i - 1, nj = j;
- if (ni < 0) {
- ni = n - 1;
- nj -= 1;
- }
- if (nj < 0) {
- break;
- }
- for (int mask = 0; mask < nn; ++mask) {
- for (bool ok : {false, true}) {
- if (dp[i][j][mask][ok] == m1) {
- continue;
- }
- //cerr << "dp[" << i << "][" << j << "][" << mask << "][" << ok << "] = " << (int)dp[i][j][mask][ok] << "\n";
- int cur = !!(mask & (1 << i));
- //cerr << "cur is " << cur << "\n";
- int left = j ? (a[i][j - 1] == '?' ? -1 : a[i][j - 1] == 'X') : 1;
- //cerr << "left is " << left << "\n";
- if (cur) {
- // wall
- if (left != 1) {
- int down = (i == n - 1) ? 1 : !!(mask & (1 << (i + 1)));
- if (!down || !cur) {
- //cerr << "remaxing dp[" << ni << "][" << nj << "][" << (mask & (~(1 << i))) << "][" << ok << "] by a wall\n";
- remax(dp[ni][nj][mask & (~(1 << i))][ok], dp[i][j][mask][ok]);
- }
- }
- if (left != 0) {
- //cerr << "remaxing dp[" << ni << "][" << nj << "][" << (mask | (1 << i)) << "][" << ok << "] by a wall\n";
- remax(dp[ni][nj][mask | (1 << i)][ok], dp[i][j][mask][ok]);
- }
- }
- else {
- // free cell
- bool nok = ok || (i == n - 1) || (j == m - 1);
- int up = i ? !!(mask & (1 << (i - 1))) : 1;
- int need_left = up ^ 1;
- if (left > -1 && left != need_left) {
- continue;
- }
- //cerr << "remaxing dp[" << ni << "][" << nj << "][" << ((mask & (~(1 << i))) | (need_left << i)) << "][" << nok << "] by a free cell\n";
- remax(dp[ni][nj][(mask & (~(1 << i))) | (need_left << i)][nok], dp[i][j][mask][ok] + 1);
- }
- }
- }
- }
- }
- int ans = dp[0][0][nn - 2][true];
- int x = 0, y = 0, mask = nn - 2;
- bool ok = true;
- if (ans == m1) {
- ans = -1;
- }
- if ((n == 1 || m == 1) && dp[0][0][nn - 2][0] != m1) {
- if (ans == -1 || ans < dp[0][0][nn - 2][0]) {
- ok = false;
- ans = max(ans, (int)dp[0][0][nn - 2][0]);
- }
- }
- if (ans > -1) {
- ans += 1;
- }
- cout << ans << "\n";
- if (ans < 0) {
- return 0;
- }
- a[0][0] = '.';
- uchar cans = ans - 1;
- while (y < m) {
- int nx = x + 1, ny = y;
- if (nx == n) {
- nx = 0;
- ++ny;
- }
- if (ny >= m) {
- break;
- }
- int cand_mask = -1;
- bool cand_ok = false;
- uchar cand_ans = m1;
- for (int nval : {0, 1}) {
- for (int nok : {0, 1}) {
- int nmask = (mask & (~(1 << nx))) | (nval << nx);
- if (dp[nx][ny][nmask][nok] == m1) {
- continue;
- }
- if (nval) {
- // wall
- int down = (nx == n - 1) ? 1 : !!(nmask & (1 << (nx + 1)));
- if (!down || !nval)
- if (dp[nx][ny][nmask][nok] != m1 && dp[nx][ny][nmask][nok] == cans) {
- cand_mask = nmask;
- cand_ok = nok;
- cand_ans = cans;
- //cerr << "ok a[" << nx << "][" << ny << "] is X\n";
- a[nx][ny] = 'X';
- break;
- }
- }
- else {
- // free cell
- bool reok = ok || (nx == n - 1) || (ny == m - 1);
- int up = nx ? !!(nmask & (1 << (nx - 1))) : 1;
- int need_left = up ^ 1;
- int left = !!(mask & (1 << nx));
- if (left != need_left) {
- continue;
- }
- if (dp[nx][ny][nmask][nok] != m1 && dp[nx][ny][nmask][nok] + 1 == cans) {
- cand_mask = nmask;
- cand_ok = nok;
- cand_ans = dp[nx][ny][nmask][nok];
- //cerr << "ok a[" << nx << "][" << ny << "] is .\n";
- a[nx][ny] = '.';
- break;
- }
- }
- }
- }
- assert(cand_mask > -1);
- mask = cand_mask;
- ok = cand_ok;
- cans = cand_ans;
- x = nx;
- y = ny;
- }
- for (int i = 0; i < n; ++i) {
- cout << a[i] << "\n";
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement