※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 14601번 문제인 샤워실 바닥 깔기 (Large)이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/14601
14601번: 샤워실 바닥 깔기 (Large)
첫 번째 줄에는 바닥의 한 변의 길이를 표현하는 자연수 K(1 ≤ K ≤ 7) 가 주어진다. 이때 바닥의 크기는 2K 가 됨에 유의하라. 두 번째 줄에는 배수구의 위치를 나타내는 자연수 x, y (1 ≤ x, y ≤ 2K)
www.acmicpc.net
타일을 알맞게 배치하는 방법은 항상 존재한다. 다음은 그 귀납적 증명이다.
i) k=1인 경우 ㄱ자 타일을 항상 배치할 수 있다는 것은 자명하다.
ii) k=p일 때 타일을 항상 배치할 수 있다고 가정하자. 이 때, k=p+1일 때 타일을 항상 배치할 수 있음을 보이면 문제를 해결할 수 있다.
한 변의 길이가 2^(p+1)인 바닥을 한 변의 길이가 2^p인 사각형 넷으로 나눠보자. 이 때, "배수구"가 있는 영역이 단 한 칸 존재한다. k=p인 케이스는 항상 타일을 배치할 수 있으므로, "배수구"가 있는 영역을 ㄱ자 타일을 이용해 채우는 것은 가능하다. 또한, 나머지 세 영역에 한 칸씩 걸치게끔 ㄱ자 타일을 하나 배치할 수 있다는 점을 관찰하자. 이와 같이 타일을 놓은 뒤 각 영역에 생긴 타일이 놓인 한 칸을 "배수구"취급하여 남은 영역들에 타일을 놓을 경우 한 변의 길이가 2^p이고 한 칸이 배수구인 바닥을 채우듯 ㄱ자 타일을 채울 수 있다는 것을 알 수 있다.
위의 증명에서 보여주는 재귀적인 방법을 구현하여 문제를 해결하자.
입력으로 주어지는 좌표가 행과 열 순이 아닌 가로좌표와 세로좌표 순임에 유의하자. 또한, 좌하단의 좌표가 (1,1), 우상단의 좌표가 (2^k,2^k)임에도 유의하자.
아래는 제출한 소스코드이다.
#include <iostream>
using namespace std;
int K;
int ans[128][128];
int num = 1;
void func(int N, int offR, int offC, int R, int C) {
if (N > 1) {
if (R < N / 2 && C < N / 2) {
ans[offR + N / 2][offC + N / 2] = ans[offR + N / 2 - 1][offC + N / 2] = ans[offR + N / 2][offC + N / 2 - 1] = num++;
func(N / 2, offR, offC, R, C);
func(N / 2, offR + N / 2, offC, 0, N / 2 - 1);
func(N / 2, offR, offC + N / 2, N / 2 - 1, 0);
func(N / 2, offR + N / 2, offC + N / 2, 0, 0);
}
else if (R < N / 2 && C >= N / 2) {
ans[offR + N / 2][offC + N / 2] = ans[offR + N / 2 - 1][offC + N / 2 - 1] = ans[offR + N / 2][offC + N / 2 - 1] = num++;
func(N / 2, offR, offC, N / 2 - 1, N / 2 - 1);
func(N / 2, offR + N / 2, offC, 0, N / 2 - 1);
func(N / 2, offR, offC + N / 2, R, C - N / 2);
func(N / 2, offR + N / 2, offC + N / 2, 0, 0);
}
else if (R >= N / 2 && C < N / 2) {
ans[offR + N / 2][offC + N / 2] = ans[offR + N / 2 - 1][offC + N / 2 - 1] = ans[offR + N / 2 - 1][offC + N / 2] = num++;
func(N / 2, offR, offC, N / 2 - 1, N / 2 - 1);
func(N / 2, offR + N / 2, offC, R - N / 2, C);
func(N / 2, offR, offC + N / 2, N / 2 - 1, 0);
func(N / 2, offR + N / 2, offC + N / 2, 0, 0);
}
else {
ans[offR + N / 2][offC + N / 2 - 1] = ans[offR + N / 2 - 1][offC + N / 2 - 1] = ans[offR + N / 2 - 1][offC + N / 2] = num++;
func(N / 2, offR, offC, N / 2 - 1, N / 2 - 1);
func(N / 2, offR + N / 2, offC, 0, N / 2 - 1);
func(N / 2, offR, offC + N / 2, N / 2 - 1, 0);
func(N / 2, offR + N / 2, offC + N / 2, R - N / 2, C - N / 2);
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> K;
int R, C; cin >> C >> R; R--, C--;
func(1 << K, 0, 0, R, C);
for (int r = (1 << K) - 1; r > -1; r--) {
for (int c = 0; c < (1 << K); c++) {
if (ans[r][c]) cout << ans[r][c] << ' ';
else cout << -1 << ' ';
}
cout << '\n';
}
}
'BOJ' 카테고리의 다른 글
[BOJ 2696 // C++] 중앙값 구하기 (0) | 2023.04.18 |
---|---|
[BOJ 14600 // C++] 샤워실 바닥 깔기 (Small) (0) | 2023.04.17 |
[BOJ 2250 // C++] 트리의 높이와 너비 (0) | 2023.04.15 |
[BOJ 2290 // C++] LCD Test (0) | 2023.04.14 |
[BOJ 9095 // C++] 1, 2, 3 더하기 (0) | 2023.04.13 |