와아아아~~ 엄청 오랜만에 문제를 풀었다 !!!!
풀이 😍
떡 종류는 1-9번!
N일 동안 떡 팔러 가는데, 그날 파는 떡의 종류들은 매일 달라진다.
전날의 떡과 오늘의 떡은 꼭 달라야 한다.
떡을 줄 방법이 있으면, 매일 호랑이한테 줄 떡을 순서대로 출력한다.
떡을 줄 방법이 없으면, -1을 출력한다.
처음에는 백 트래킹을 생각했다. 호랑이한테 줄 수 있는 떡의 경우들로 가지를 뻗어보다가, 처음으로 정답까지(N일 동안 호랑이한테 다른 떡 주는 경우) 가면 그만 탐색하면 되겠다고 생각했다 !! 또 N이 최대 1000이니까 그 정도면 dfs 를 돌릴 수 있다고 생각했다!
dfs 함수를 만들고 그 인자로 며칠인지(day), 그 동안 호랑이한테 준 떡들(history)을 넘겼다. 매일 호랑이한테 줄 수 있는 떡들로 다 가지를 뻗어보는 것이다! 그 동안 호랑이한테 준 떡을 아니까, 전날 호랑이한테 준 떡도 알 수 있다. 전날 준 떡과 줄 수 있는 떡이 다를 때만 가지를 뻗으면 된다.
이런 식으로 했더니, 처음에는 시간 초과가 나왔다.
게시판에 문제인 이유와 해결 방법이 나와있었다 !!
만약에 1-998일까지는 매일 떡을 1-9번 다 만들고, 999-1000일은 똑같은 떡을 만드는 경우를 생각해보면..
가지가 9(첫날 고르는 떡) X 8(다른 날들은 그 전날 고른 떡은 고를 수 없음)의 997제곱 X 1(999일에 고를 수 있는 떡이 1개) X 1(1000일에 고를 수 있는 떡이 1개) 만큼 뻗어지는 것이다. 엄청 엄청 경우가 많으니.. 시간 초과가 나는 것이다.
게시판에서 며칠인지, 그 전날 어떤 떡을 호랑이에게 주었는지로 방문 체크를 하면 된다는 걸 보았다. 그래서 2차원 리스트를 만들어서, 겉 리스트에는 몇번째 날인지/ 안의 리스트에는 전날 어떤 떡을 호랑이에게 주었는지를 두고 방문 체크를 했다.
만약 이미 True로 체크되었으면, 특정일에 호랑이에게 특정 떡을 줬을 때 경우 & 그리고 그 이후 가지들은 이미 본 것이니까 안 봐도 된다!
백트래킹 만으로 안되고 방문 체크까지 해야 해서 재미있었다 :)
코드 🐼
import sys
sys.setrecursionlimit(10**4)
input=sys.stdin.readline
N=int(input())
rice_cakes_per_day = [] * N
for k in range(N):
rice_cake = input().split()[1:]
rice_cakes_per_day.append(rice_cake)
def dfs(day, history):
global flag
if flag:
return
if day == N:
print('\n'.join(history.split()))
flag = True
return
for cake in rice_cakes_per_day[day]: # 그 날의 떡 보면서
# 첫날이라면
if day == 0:
visited[day+1][int(cake)] = True
dfs(day+1, history+cake+' ') # 무조건 그 떡을 주고, 다음날로 넘어가기
# 첫날 아닌데 전날과 안 겹치고 방문 안 했으면
elif cake != history[-2] and not visited[day+1][int(cake)]:
visited[day+1][int(cake)] = True
dfs(day+1, history+cake+' ') # 그 떡을 주고, 다음날로 넘어가기
visited = [[False]*10 for _ in range(N+1)] # 날짜, 전날 준 떡
flag = False
dfs(0,'')
if flag == False: # 떡 줄 방법이 없으면 -1 출력
print(-1)
'즐거운 PS 👩💻🥰' 카테고리의 다른 글
[백준/파이썬] 1026: 보물 (0) | 2023.02.18 |
---|---|
[백준/python] 16960: 스위치와 램프 (2) | 2022.08.25 |
[백준/파이썬] 3079: 입국심사 (0) | 2022.06.04 |
[백준/파이썬] 2023: 신기한 소수 (0) | 2022.05.30 |
[백준/파이썬] 1966: 프린터 큐 (0) | 2022.05.18 |