728x90
시간 제한 1초, 메모리 제한 128MB
# 조건
- 숫자 1, 2, 3으로만 이루어지는 수열이 있다.
- 임의의 길이의 인접한 두 개의 부분 수열이 동일한 것이 있으면, 그 수열을 나쁜 수열이라고 부른다.
- 그렇지 않은 수열은 좋은 수열이다.
- 다음은 나쁜 수열의 예이다.
- 33
- 32121323
- 123123213
- 다음은 좋은 수열의 예이다.
- 2
- 32
- 32123
- 1232123
- 길이가 N인 좋은 수열들을 N자리의 정수로 보아 그중 가장 작은 수를 나타내는 수열을 구하는 프로그램을 작성하라.
- 예를 들면, 1213121과 2123212는 모두 좋은 수열이지만 그 중에서 작은 수를 나타내는 수열은 1213121이다.
입력
- 입력은 숫자 N하나로 이루어진다.
- N은 1 이상 80이하이다.
출력
- 첫 번째 줄에 1,2,3으로만 이루어져 잇는 길이가 N인 좋은 수열들 중에서 가장 작은 수를 나타내는 수열만 출력한다.
- 수열을 이루는 1,2,3들 사이에는 빈칸을 두지 않는다.
# 접근 방법
- 전체 수열을 만들고 체크하면 시간 초과가 발생한다.
- 따라서, dfs와 백트래킹을 사용하여 풀어준다.
- 사용할 수 있는 수는 1, 2, 3이므로 순열을 만들 반복문은 range(1, 4)의 범위로 돌려준다.
- 수열 뒤에 수를 추가해주며 나쁜 수열인 경우엔 return을 한다.
- 좋은 수열인지 나쁜 수열인지 체크하는 방법은
- 123123의 경우
- 1자리
- 1, 2, 3, 1, 2, 3
- 2자리
- 12, 31, 23
- 23, 12와 같이 체크해야되는데
- 3자리
- 123 123
- 1자리
- 숫자를 추가하는 경우 좋은 수열인 경우만 추가하였으니 뒤의 2개만 확인해주면 된다.
- 위의 예를 다시 보면 1 2 3 1 2 에서 뒤에 3을 추가하는 경우
- 1자리 비교는 2 와 3만 비교
- 2자리는 31과 23을 비교
- 3자리인 경우 123 123을 비교
- 즉, 1 ~ 현재 길이 // 2 + 1 범위로 비교를 하며
- -i, -2 * i ~ -i 를 비교해주면 된다.
- 길이가 N과 같다면 좋은 수열이면서 최소를 만족한 경우이므로 바로 출력해주면 된다.
import sys
input = sys.stdin.readline
# idx는 현재 추가된 수의 인덱스 = 만들고 있는 수열의 현재 길이
def good_permu(idx):
# 이미 앞에는 좋은 수열만 추가되었으므로
# 추가된 수를 포함하며 뒤에서 2개만 절반의 길이만큼만 체크해주면 된다.
# 즉, 123123의 경우
# 뒤에서 3 과 2, 31 과 23, 123 과 123을 비교해준다.
for i in range(1, idx//2 + 1):
if result[-i:] == result[-2*i:-i]:
return 0
if idx == N:
print(*result, sep='')
return 1
for i in range(1, 4):
result.append(i)
if good_permu(idx+1):
return 1
result.pop()
N = int(input())
result = []
good_permu(0)
728x90
'ALGORITHM > 백트래킹' 카테고리의 다른 글
[백준 15664번] 파이썬 - N과 M(10) (0) | 2023.08.16 |
---|---|
[프로그래머스 Lv3] 파이썬 - 사라지는 발판 (0) | 2023.08.02 |
[백준 1189번] 파이썬 - 컴백홈 (0) | 2023.05.17 |
[백준 1799번] 파이썬 - 비숍 (0) | 2023.04.30 |
[백준 14888번] 파이썬 - 연산자 끼워넣기 (0) | 2023.04.07 |