문제
https://www.acmicpc.net/problem/1495
Day Of Mourning의 기타리스트 강토는 다가오는 공연에서 연주할 N개의 곡을 연주하고 있다. 지금까지 공연과는 다른 공연을 보여주기 위해서 이번 공연에서는 매번 곡이 시작하기 전에 볼륨을 바꾸고 연주하려고 한다.
먼저, 공연이 시작하기 전에 각각의 곡이 시작하기 전에 바꿀 수 있는 볼륨의 리스트를 만들었다. 이 리스트를 V라고 했을 때, V[i]는 i번째 곡을 연주하기 전에 바꿀 수 있는 볼륨을 의미한다. 항상 리스트에 적힌 차이로만 볼륨을 바꿀 수 있다. 즉, 현재 볼륨이 P이고 지금 i번째 곡을 연주하기 전이라면, i번 곡은 P+V[i]나 P-V[i] 로 연주해야 한다. 하지만, 0보다 작은 값으로 볼륨을 바꾸거나, M보다 큰 값으로 볼륨을 바꿀 수 없다.
곡의 개수 N과 시작 볼륨 S, 그리고 M이 주어졌을 때, 마지막 곡을 연주할 수 있는 볼륨 중 최댓값을 구하는 프로그램을 작성하시오. 모든 곡은 리스트에 적힌 순서대로 연주해야 한다.
입력
첫째 줄에 N, S, M이 주어진다. (1 ≤ N ≤ 50, 1 ≤ M ≤ 1,000, 0 ≤ S ≤ M) 둘째 줄에는 각 곡이 시작하기 전에 줄 수 있는 볼륨의 차이가 주어진다. 이 값은 1보다 크거나 같고, M보다 작거나 같다.
출력
첫째 줄에 가능한 마지막 곡의 볼륨 중 최댓값을 출력한다. 만약 마지막 곡을 연주할 수 없다면 (중간에 볼륨 조절을 할 수 없다면) -1을 출력한다.
풀이
지난 번 문제 '퇴사'와는 다르게 상한선이 있고 볼륨을 감소할 수 있었다.
그래서 모든 경우의 수를 탐색해야 할 것 같아 dfs로 풀었다.
n, s, m = map(int, input().split())
vol = list(map(int, input().split()))
maxv = -1;
def dfs(i, value):
global maxv
if i == n:
maxv = max(maxv, value)
return
if value + vol[i] <= m:
dfs(i+1, value+vol[i])
if value - vol[i] >= 0:
dfs(i+1, value-vol[i])
dfs(0, s)
print(maxv)
결과는 4퍼에서 시간초과 ㅠ
역시 dp로 풀어야 하는 문제인가보다.
dfs로는 트리형식으로
2^0 + 2^1 + 2^2 + ... + 2^n번 탐색해야하니 아래 식과 같이 총 O(n^3)이었지 않았을까 싶다.. (뇌피셜)
다른 분의 글을 참고하니 m X n 사이즈의 배열을 만들어 처리하셨다. (https://jshong1125.tistory.com/56)
n, s, m = map(int, input().split())
vol = list(map(int, input().split()))
dp = [[0] * (m+1) for _ in range(n+1)]
dp[0][s] = 1
for i in range(n):
for j in range(m+1):
if dp[i][j]:
if j + vol[i] <= m:
dp[i+1][j+vol[i]] = 1
if 0 <= j - vol[i]:
dp[i+1][j-vol[i]] = 1
for i in range(m, -1, -1):
if dp[n][i]:
print(i)
exit(0)
print(-1)
bfs는 n이 커질수록 중복연산이 많아지는데 이렇게 하면 중복 없이 O(n*m)으로 처리할 수 있다..! 이렇게 바꾸니 통과했다.
dp 배열과 출력값이다.
'알고리즘 스터디' 카테고리의 다른 글
[백준] 12026 BOJ 거리 - 파이썬 (0) | 2022.02.06 |
---|---|
[백준] 11058 크리보드 파이썬 (0) | 2022.02.02 |
[백준] 15989 1,2,3 더하기 4 파이썬 (0) | 2022.01.23 |
[백준] 1890 점프 파이썬 (0) | 2022.01.23 |
[백준] 16930 달리기 파이썬 (0) | 2022.01.16 |