BOJ 25713 - 괴도 인하

image.png

항상 $\to$나 $\downarrow$로 이동하므로 어떤 직사각형에 진입할 수 있는 경우는 저 두 가지이다.

그러므로 각 직사각형마다 제일 위 행과 제일 왼쪽 열만 각각의 경우에 대해 imos법으로 구간합을 구해두자.

그런다음 dp를 돌려주면 된다.

void solve() {
   struct stat st;
   fstat(0, &st);
   char *p = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, 0, 0);
   auto readInt = [&]() {
      int ret = 0;
      for (char c = *p++; c & 16; ret = 10 * ret + (c & 15), c = *p++);
      return ret;
   };
   int Y = readInt(), X = readInt(), K = readInt();
   cin >> Y >> X >> K;
   vector<array<int, 4>> C(K);

   vvi psum_t(Y + 1, vi(X + 1));
   auto psum_r = psum_t;

   for (auto &[y1, x1, y2, x2]: C) {
      y1 = readInt() - 1, x1 = readInt() - 1, y2 = readInt() - 1, x2 = readInt() - 1;
      if (y1 > y2) swap(y1, y2);
      if (x1 > x2) swap(x1, x2);

      psum_t[y1][x1]++;
      psum_t[y1][x2 + 1]--;
      psum_t[y1 + 1][x1]--;
      psum_t[y1 + 1][x2 + 1]++;
      psum_r[y1][x1]++;
      psum_r[y1][x1 + 1]--;
      psum_r[y2 + 1][x1]--;
      psum_r[y2 + 1][x1 + 1]++;
   }

   for (int y = 0; y < Y; y++)
      for (int x = 1; x < X; x++) {
         psum_t[y][x] += psum_t[y][x - 1];
         psum_r[y][x] += psum_r[y][x - 1];
      }
   for (int y = 1; y < Y; y++)
      for (int x = 0; x < X; x++) {
         psum_t[y][x] += psum_t[y - 1][x];
         psum_r[y][x] += psum_r[y - 1][x];
      }

   vvi dp(Y, vi(X, 1e9));
   dp[0][0] = psum_t[0][0];
   for (int y = 0; y < Y; y++) {
      for (int x = 0; x < X; x++) {
         if (y == 0 && x == 0) continue;

         if (y) {
            dp[y][x] = min(dp[y][x], dp[y - 1][x] + psum_t[y][x]);
         }
         if (x) {
            dp[y][x] = min(dp[y][x], dp[y][x - 1] + psum_r[y][x]);
         }
      }
   }
   cout << dp[Y - 1][X - 1];

}

Tags:

Categories:

Updated:

Comments