Jinsoolve.

Categories

Tags

3월 안에는 꼭...

Portfolio

About

백준 6569 - 몬드리안의 꿈

Created At: 2025/02/28

2 min read

위 포스트는 백준 6569 - 몬드리안의 꿈에 대한 해설입니다.

풀이

........................
채워짐채워짐채워짐채워짐채워짐채워짐채워짐채워짐
채워짐채워짐채워짐채워짐w-1.........
...210(h,w)

위와 같이 큰 직사각형이 존재한다고 하자.
dp[h][w][bit] := bit상태일 때, (h,w)부터 끝까지 큰 직사각형을 2x1 직사각형으로 채우는 경우의 수라 하자. (이때 (0,0) ~ (h-1,w-1) 영역은 모두 채워져 있음을 가정한다.)

여기서 bit는 w개의 bit로 이루어져 있는데, 이는 (w-1) (w-2) ... (2) (1) (0) 을 의미한다.
각 비트는 채워진 여부를 의미한다. 0이면 비어있고 1이면 채워져 있다.

이때 다음과 같이 풀면 된다.

  1. (h-1,w)가 빈 경우,
    이 경우 (h,w)에서 세로로 세워진 2x1 직사각형을 놓치 않으면 (h-1,w)을 채울 방법이 앞으로 더 이상 없으므로 무조건 채워주어야 하므로 무조건 세로로 직사각형을 놓는다.
  2. Else
    아래 1,2 경우를 더 해준다.
    1. 현재 칸에 아무런 직사각형을 놓치 않는다.
    2. (h,w-1)가 빈 경우, 눕혀진 직사각형 1x2 직사각형을 놓는다.
  3. 끝까지 도달한 경우 마지막 행이 채워졌는지의 여부를 갖고 있는 bit가 모두 1로 이루어져 있는지 확인하여 모두 1이라면 1을, 아니라면 0을 반환해준다.

코드

cpp
1#include <bits/stdc++.h> 2 3#define endl "\n" 4#define all(v) (v).begin(), (v).end() 5#define all1(v) (v).begin()+1, (v).end() 6#define For(i, a, b) for(int i=(a); i<(b); i++) 7#define FOR(i, a, b) for(int i=(a); i<=(b); i++) 8#define Bor(i, a, b) for(int i=(a)-1; i>=(b); i--) 9#define BOR(i, a, b) for(int i=(a); i>=(b); i--) 10#define ft first 11#define sd second 12 13using namespace std; 14using ll = long long; 15using lll = __int128_t; 16using ulll = __uint128_t; 17using ull = unsigned long long; 18using ld = long double; 19using pii = pair<int, int>; 20using pll = pair<ll, ll>; 21using ti3 = tuple<int, int, int>; 22using tl3 = tuple<ll, ll, ll>; 23 24template<typename T> using ve = vector<T>; 25template<typename T> using vve = vector<vector<T>>; 26 27template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; } 28template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; } 29 30const int INF = 987654321; 31const int INF0 = numeric_limits<int>::max(); 32const ll LNF = 987654321987654321; 33const ll LNF0 = numeric_limits<ll>::max(); 34 35int H, W; 36ll dp[11][11][1<<11]; 37 38ll sol(int h, int w, int bit) { 39 if(h==H) return (bit == ((1<<W)-1)); 40 ll &ret = dp[h][w][bit]; 41 if(ret != -1) return ret; 42 int nh = h, nw = w+1; 43 if(nw == W) nh++, nw=0; 44 if(h!=0 and (bit & (1<<(W-1))) == 0) return ret = sol(nh,nw,(bit*2+1)%(1<<W)); 45 ret = sol(nh,nw,(bit*2)%(1<<W)); 46 if(w!=0 and (bit & 1) == 0) ret += sol(nh,nw,((bit+1)*2+1)%(1<<W)); 47 return ret; 48} 49 50int main(void) { 51 ios_base::sync_with_stdio(false); 52 cin.tie(nullptr); 53 cout.tie(nullptr); 54 55 while(true) { 56 cin >> H >> W; 57 if(H==0 and W==0) break; 58 memset(dp, -1, sizeof dp); 59 cout << sol(0,0,0) << endl; 60 } 61 62 63 return 0; 64}

관련 포스트가 12개 있어요.

백준 1787 - 문자열의 주기 예측

위 포스트는 백준 1787 - 문자열의 주기 예측 의 해설입니다. 결국 부분 문자열에서 가장 짧으면서 일치하는 Prefix와 Suffix를 찾으면 된다. (해당 길이를 전체…

2025/03/05

NEW POST
profile

김진수

Currently Managed

Currently not managed

© 2025. junghyeonsu & jinsoolve all rights reserved.