https://www.acmicpc.net/problem/2602
로직
dp 문제, 조금 복잡
다리의 왼쪽부터 오른쪽으로 순회
다리의 종류(천사,악마) 별로 적혀진 알파벳이 다름
다리에 적혀진 알파벳이, 만들어야 하는 문자열에 어디에 쓰이는지 확인
- 예를 들어 "RIRNRGRS" 라는 문자열에서 R은
[0,2,4,6]
에서 사용됨 - 다리에 적힌 알파벳이 R이라면 0번, 2번, 4번, 6번에서 사용 될 수 있음
- 2,4,6번의 경우 조건이 완성된 경우에 사용이 가능
- 2번을 예시로 들면 그 전에 R과 I가 완성 되어 있는 경우 사용 가능
- 예를 들어 "RIRNRGRS" 라는 문자열에서 R은
다리를 idx번 지났을때, 문자열의 완성 정도를 기록
- 다리4칸을 건넜을 때, 문자열이 1번까지 완성되는 경우의 수 3개, 2번까지 완성된 경우의 수 1개 ....
예시
- 예제 1번 문자열:RGS, 악마: RINGSR, 천사:GRGGNS 이 주어졌을 경우
- 악마기록 :
[0,0,0]
, 악마기록 :[0,0,0]
으로 초기화 (3칸인 것은 만들려는 문자열이 3칸이기에) - 다리 왼쪽부터 순회
첫번째 턴(다리 0번)
- 악마 다리는 R, 천사 다리는 G
- 천사 기록:
[0,0,0]
그대로- G를 사용하는 경우는 문자열 1번인데, 그 전에 악마다리에서 첫번째까지 완성된 경우의 수가 0(악마 기록
[0]
)
- G를 사용하는 경우는 문자열 1번인데, 그 전에 악마다리에서 첫번째까지 완성된 경우의 수가 0(악마 기록
- 악마 기록:
[1,0,0]
변화- R이 사용 되는 곳은 문자열의 0번, 사전 조건이 없어 바로 추가
- 0번까지 완성된 경우의 수가 1개 증가했으므로 0->1로 변경
두번째 턴(다리 1번)
- 악마 다리는 I, 천사 다리는 R
- 악마 기록 :
[1,0,0]
그대로, I는 문쟈열에서 사용되지 않기에 pass - 천사 기록 :
[1,0,0]
으로 변화- R은 문자열의 0번째에서 사용
세번째 턴(다리 2번)
- R은 문자열의 0번째에서 사용
- 악마 다리는 N, 천사 다리는 G
- 악마 기록 :
[1,0,0]
그대로, N은 문자열에서 사용X - 천사 기록 :
[1,1,0]
변화- G는 문자열에서 1번째에서 사용됨
- 이를 위해선 악마다리에서 0번까지 완료된 경우가 필요
- 악마다리에서 0번까지 완료된 경우의 수는 1개(
악마기록[0] == 1
)이므로 0->1로 변화네번쨰 턴 (다리3번)
- 악마 다리는 G, 천사 다리는 G
- 악마 기록 :
[1,1,0]
변화- G는 문자열에서 1번째에서 사용됨
- 이를 위해선 천사다리에서 0번까지 완료된 경우가 필요
- 천사다리에서 0번까지 완료된 경우의 수는 1개(
천사기록[0] == 1
)이므로 0->1로 변화
- 천사 기록 :
[1,2,0]
변화- 마찬가지로 악마다리에서 0번까지 완료된 경우의 수(
악마기록[0] == 1
) 만큼 증가하여 1->2로 변화
- 마찬가지로 악마다리에서 0번까지 완료된 경우의 수(
다섯번째 턴 (다리4번)
- 악마 다리는 S, 천사는 N
- 악마 기록 :
[1,1,2]
변화- S는 문자열 2번쨰에서 사용됨
- 이를 활용하기 위해서는 천사 다리에서 1번까지 완성된 경우가 필요
- 그렇기에
악마 기록[2]
가천사 기록[1] == 2
만큼 추가
나머진 생략
# 코드는 다리가 2개가 아닌 3,4,5 ... 개로 늘어나면 어떻게 하지?라는 생각으로 작성하여 복잡
def solution(sentence:str,bridge:list[str])->int:
# 각 알파벳 idx들 기록
alphaTotal = {"R":[],"I":[],"N":[],"G":[],"S":[]}
S = len(sentence)
for i in range(S):
alpha = sentence[i]
alphaTotal[alpha].append(i)
B = len(bridge)
L = len(bridge[0])
check = [[0]*S for _ in range(B)]
for idx in range(L): # 다리idx
temp = list() # temp를 사용하는 이유는 각 다리의 변화를 한번에 업데이트 하기 위함
for i in range(B): # 어떤 다리인지, 천사 or 악마 다리
alpha = bridge[i][idx]
for num in alphaTotal[alpha]: # num은 해당 알파벳이 문자열에서 사용되는 위치
if num == 0:
temp.append((i,num,1))
else:
value = 0 # 자기 다리를 제외한 경우의 수의 합
for v in range(B):
if v == i:continue
value += check[v][num-1]
temp.append((i,num,value))
for r,c,cnt in temp:
check[r][c] += cnt
ansValue = 0
for i in range(B):
ansValue += check[i][S-1]
return ansValue
sentence = input()
devil = input()
angle = input()
ans = solution(sentence,[devil,angle])
print(ans)
'알고리즘 문제 풀이 > Python' 카테고리의 다른 글
python 백준 2469 사다리 타기 (0) | 2024.07.10 |
---|---|
python 백준 1495 기타리스트 (0) | 2024.07.04 |
python 백준 1099 알 수 없는 문장 (1) | 2024.06.12 |
Python 백준 1756 피자굽기 (0) | 2024.06.03 |
python 백준 14719 빗물 (0) | 2024.05.28 |