Submission #957194

# Submission time Handle Problem Language Result Execution time Memory
957194 2024-04-03T07:03:19 Z robertopino Connect (CEOI06_connect) C++14
4 / 100
500 ms 16316 KB
#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector")
#include <bits/stdc++.h>
using namespace std;
 
#define fore(i, l, r) for (auto i = (l) - ((l) > (r)); i != (r) - ((l) > (r)); i += 1 - 2 * ((l) > (r)))
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define f first
#define s second
#define pb push_back
 
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...)
#endif
 
using ld = long double;
using lli = long long;
using ii = pair<int, int>;
 
const int N = 12, M = 40;
int dp[M][N][1 << N];
const int N_BITSET = 7;
template <class T>
bool umin(T& a, T b) {
  return (a = min(a, b)) == b;
}
 
int main() {
  cin.tie(0)->sync_with_stdio(0), cout.tie(0);
  int n, m;
  cin >> n >> m;
  cin.ignore();
  cin.ignore();
  vector<string> board(n);
  debug(n, m);
  int foobar = 0;
  fore (i, 0, n) {
    getline(cin, board[i]);
    // assert(sz(board[i]) == m);
    debug(board[i]);

    fore (j, 0, m) {
      foobar += board[i][j] == 'X';
    }
  }
  
  foobar /= 2;
  n /= 2, m /= 2;
  debug(n, m);
  int completeMask = (1 << m) - 1;

  #define coord(x) (x * 2 + 1)
  auto isAFigure = [&] (int r, int c) -> bool {
    if (r < 0 || c < 0) {
      debug("isAFigure: Coordinates out of range");
      return false;
    }
    debug(r, c);
    r = coord(r), c = coord(c);
    debug(r, c, board[r][c]);
    return board[r][c] == 'X';
  };
 
  auto blocked = [&] (int r1, int c1, int r2, int c2) -> bool {
    debug(r1, c1, r2, c2);
    if (r1 < 0 || c1 < 0 || r2 < 0 || c2 < 0) {
      debug("blocked: Coordinates out of range");
      return false;
    }
 
    r1 = coord(r1), c1 = coord(c1);
    r2 = coord(r2), c2 = coord(c2);
    bool thereIsAWall = false;
    if (r1 == r2) { // hor
      debug("horizontal");
      if (c1 > c2) {
        swap(c1, c2);
      }
      assert(c1 + 2 == c2);
      thereIsAWall = board[r1][c1 + 1] == '|';
    } else { // ver
      debug("vertical");
      assert(c1 == c2);
      if (r1 > r2) {
        swap(r1, r2);
      }
      assert(r1 + 2 == r2);
      thereIsAWall = board[r1 + 1][c1] == '-';
    }
 
    debug(r1, c1, r2, c2, thereIsAWall);
    return thereIsAWall;
  };

  auto additionalCost = [&] (int r, int ith, int mask) -> bool {
    if (~mask & (1 << ith) && isAFigure(r - 1, ith)) {
      return true;
    }
    
    return false;
  };


  auto verify = [&] (int r, int c, int mask) -> bool {
    bool invalid = false;
    if (r > 0) {
      fore (ith, c, m) {
        bool bit = mask & (1 << ith);
        invalid |= bit & !isAFigure(r - 1, ith) & blocked(r - 1, ith, r, ith);
        invalid |= !bit & isAFigure(r - 1, ith) & blocked(r - 1, ith, r, ith);
      }
    }

    return invalid;
  };


  auto canPlaceAConnection = [&] (int r, int ith, int mask) -> bool {
    if (mask & (1 << ith)) {
      return isAFigure(r - 1, ith) ? true : false;
    } else {
      return isAFigure(r - 1, ith) ? false : true;
    }
  };

  auto createNewPair = [&] (int r, int c, int mask) {
    debug("createNewPair");
    int me = dp[r][c][mask];
    if (canPlaceAConnection(r, c, mask)) { // create a new pair (a, b)
      int a = c;
      for (int b = c + 1; b < m; b++) {
        if (blocked(r, b - 1, r, b) || !canPlaceAConnection(r, b, mask)) {
          break;
        }
        
        int newMask = mask | (1 << a) | (1 << b);
        int newC = b + 1;
        int len = abs(a - b) + 1;
        int cost = me + (len * 2 - 1);
        bitset<N_BITSET> newMaskBitset(newMask);
        debug(a, b, newMaskBitset, newC, len, cost);
        umin(dp[r][newC][newMask], cost);
        if (isAFigure(r, b)) {
          break;
        }
      }
    }
    debug("");
    debug("");
  };


  // auto bitIsActuallySet = [&] (int r, int ith, int mask) -> bool {
  //   if (mask & (1 << ith)) 
  //     return true;
  //   return isAFigure(r - 1, ith);
  // };

  auto bitIsActuallySet = [&] (int r, int ith, int mask) -> bool {
    if (mask & (1 << ith))
      return isAFigure(r - 1, ith) == false;
    return isAFigure(r - 1, ith) == true;
  };

  auto turnOffBit = [&] (int& mask, int ith) {
    mask &= completeMask ^ (1 << ith);
  };

  auto turnOnBit = [&] (int& mask, int ith) {
    mask |= (1 << ith);
  };

  auto continueAConnection = [&] (int r, int c, int mask) {
    int me = dp[r][c][mask];
    debug("continueAConnection");
    // move next connection to c
    int index = -1;
    fore (ith, c, m) {
      if (bitIsActuallySet(r, ith, mask)) {
        index = ith;
        break;
      }
    }

    debug(index);
    if (index != -1) {
      debug("left");
      for (int ith = index; ith >= c; ith--) {
        if (ith != index && (blocked(r, ith, r, ith + 1) || bitIsActuallySet(r, ith, mask))) {
          break;
        }

        // move connection from index to ith if possible
        int newMask = mask;
        debug(index, ith);
        debug(newMask);
        turnOffBit(newMask, index);
        turnOnBit(newMask, ith);
        debug(newMask);
        bitset<N_BITSET> newMaskBitset(newMask);
        int newC = max(ith, index) + 1;
        int len = abs(index - ith) + 1;
        int cost = me + (len * 2 - 1) + 1 + additionalCost(r, index, mask);
        debug(ith, newC, len, cost, newMaskBitset);
        umin(dp[r][newC][newMask], cost);
        if (isAFigure(r, ith)) {
          break;
        }
      }

      // right
      debug("right");
      if (!isAFigure(r, c)) {
        for (int ith = index + 1; ith < m; ith++) {
          if (bitIsActuallySet(r, ith, mask) || blocked(r, ith - 1, r, ith)) { // is blocked
            break;
          }

          // move end from index to ith if possible
          int newMask = mask;
          turnOffBit(newMask, index);
          turnOnBit(newMask, ith);

          int newC = max(ith, index) + 1;
          int len = abs(index - ith) + 1;
          int cost = me + (len * 2 - 1) + 1 + additionalCost(r, index, mask);
          umin(dp[r][newC][newMask], cost);
          if (isAFigure(r, ith)) {
            break;
          }
        }
      }
    }
  };

  auto meetTwoConnections = [&] (int r, int c, int mask) {
    int me = dp[r][c][mask];
    debug("meetTwoConnections");
    if (bitIsActuallySet(r, c, mask) && !isAFigure(r, c)) {
      fore (ith, c + 1, m) {
        if (isAFigure(r, ith) || blocked(r, ith - 1, r, ith)) {
          break;
        }

        if (!bitIsActuallySet(r, ith, mask)) {
          continue;
        }

        int a = c, b = ith;
        int newC = ith + 1;
        int newMask = mask;
        turnOffBit(newMask, a);
        turnOffBit(newMask, b);
        bitset<N_BITSET> newMaskBitset(newMask);
        int len = abs(a - b) + 1;
        int cost = me + (len * 2 - 1) + 2 + additionalCost(r, a, mask) + additionalCost(r, b, mask);
        debug(a, b, newC, newMaskBitset, me, len);
        umin(dp[r][newC][newMask], cost);
        break;
      }
    }
  };

  memset(dp, 63, sizeof(dp));
  dp[0][0][0] = 0;
  
  fore (r, 0, n) {
    fore (c, 0, m + 1) {
      fore (mask, 0, 1 << m) {
        auto me = dp[r][c][mask];
        bitset<N_BITSET> maskBitset(mask);
        debug(r, c, mask, me);

        if (c == m) {
          debug("next row");
          umin(dp[r + 1][0][mask], me);
          continue;
        }

        bool invalid = verify(r, c, mask);
        if (invalid) {
          debug("invalid, cannot continue");
          continue;
        }
 
        if (!bitIsActuallySet(r, c, mask)) {
          debug("do nothing");
          int newMask = mask;
          turnOffBit(newMask, c);
          umin(dp[r][c + 1][newMask], me);
        }
 
        createNewPair(r, c, mask);
        continueAConnection(r, c, mask);
        meetTwoConnections(r, c, mask);
        debug("---------------------------------------------");
      }
      debug("");
    }
    debug("");
  }
  debug("");
  
  int mask = 0;
  fore (i, 0, m) {
    if (isAFigure(n - 1, i))
      mask |= 1 << i;
  }

  debug(*min_element(all(dp[n][0])));
  cout << dp[n][0][mask] - foobar << '\n';
  return 0;
}
 
/* Please, check the following:
 * int overflow, array bounds
 * special cases (n=1?)
 * do smth instead of nothing and stay organized
 * write down your ideas
 * DON'T get stuck on ONE APPROACH!
 * ASK for HELP from your TEAMMATES
 */
# Verdict Execution time Memory Grader output
1 Partially correct 2 ms 8028 KB Partially correct (80% score). Wrong board
2 Incorrect 2 ms 8028 KB Wrong score! (37, expected 40)
3 Incorrect 4 ms 8028 KB Wrong score! (1061109555, expected 74)
4 Incorrect 2 ms 8028 KB Wrong score! (27, expected 28)
5 Incorrect 17 ms 8024 KB Wrong score! (77, expected 102)
6 Runtime error 10 ms 15964 KB Execution killed with signal 11
7 Incorrect 176 ms 8120 KB Wrong score! (-1, expected 72)
8 Runtime error 54 ms 16316 KB Execution killed with signal 11
9 Runtime error 58 ms 16060 KB Execution killed with signal 11
10 Runtime error 12 ms 15960 KB Execution killed with signal 11
11 Runtime error 53 ms 16156 KB Execution killed with signal 11
12 Runtime error 9 ms 16060 KB Execution killed with signal 11
13 Runtime error 31 ms 16056 KB Execution killed with signal 11
14 Runtime error 8 ms 15964 KB Execution killed with signal 11
15 Runtime error 54 ms 16080 KB Execution killed with signal 11
16 Runtime error 8 ms 15964 KB Execution killed with signal 11
17 Execution timed out 1004 ms 8028 KB Time limit exceeded
18 Runtime error 9 ms 15964 KB Execution killed with signal 11
19 Runtime error 8 ms 15964 KB Execution killed with signal 11
20 Runtime error 10 ms 15960 KB Execution killed with signal 11