문제 : https://www.acmicpc.net/problem/1802
1802번: 종이 접기
첫째 줄에 테스트 케이스의 개수 T가 주어진다. T는 1000보다 작거나 같은 자연수이다. 둘째 줄부터 T개의 줄에 각각의 종이가 어떻게 접혀있는지가 주어진다. 종이의 정보는 문자열로 주어지며, 1
www.acmicpc.net
문제 파악하기
항상 종이를 절반씩 접는다고 할 때, 제시된 문자열로 종이를 접을 수 있는지 확인하는 문제입니다. 종이를 절반씩 접게 되면, 항상 접은 부분을 중심으로 양쪽에는 반대로 접힌 흔적이 남게 됩니다. 이를 활용하면 문제를 해결할 수 있습니다.
문제 해결하기
종이를 접어 생기는 흔적은 항상 중앙에 생기게 됩니다. 그리고 생긴 흔적을 중심으로 항상 반대로 접히게 됩니다. 예를 들어 문자열이 1000110 인 경우, 처음 접은 흔적은 1000110 정중앙에 위치한 0입니다. 그 다음 접은 흔적은 1000110 가운데 0을 기준으로 나눠진 3개의 흔적 중 중앙에 위치한 0과 1입니다. 마지막으로 접은 흔적은 1000110 남은 4개의 흔적이 됩니다. 따라서 이 문자열은 종이를 총 3번 접었으며, 우리는 이렇게 종이를 접을 때마다 나올 수 있는 문자열인지 확인하면 문제를 해결할 수 있습니다.
소스코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#include <stdio.h>
#include <string.h>
#define NMAX 3010
int T;
char inp[NMAX];
int l, r, mid, f;
void sv(int l, int r) {
int mid, ll, rr;
if(!f or l>r) return;
mid = (l+r)/2;
for(ll=mid-1,rr=mid+1;ll>=l and rr<=r;ll--,rr++) {
if(inp[ll] == inp[rr]) {
f = 0;
return;
}
}
sv(l, mid-1);
sv(mid+1, r);
}
int main() {
scanf("%d", &T);
while(T--) {
inp[0] = '\0';
scanf("%s", inp);
f = 1;
sv(0, strlen(inp)-1);
if(f) printf("YES\n");
else printf("NO\n");
}
}
|
cs |
후기
문제를 해결하는 알고리즘은 어렵지 않지만 떠올리는 추상화 과정이 어려운 문제라고 생각합니다. 분할 정복을 연습하는 사람에게 추천하고 싶은 문제입니다.
'문제 노트 > 백준' 카테고리의 다른 글
사과와 바나나( BOJ 3114 ) (0) | 2021.10.04 |
---|---|
낚시왕( BOJ 17143) (0) | 2021.09.26 |
7-세그먼트 디스플레이( BOJ 18118 ) (0) | 2021.09.15 |
K번째 수( BOJ 1300 ) (0) | 2021.09.10 |
습격자 초라기( BOJ 1006 ) (0) | 2021.09.06 |