백준 1495번 기타리스트

 Description

Day Of Mourning의 기타리스트 강토는 다가오는 공연에서 연주할 N개의 곡을 연주하고 있다. 지금까지 공연과는 다른 공연을 보여주기 위해서 이번 공연에서는 매번 곡이 시작하기 전에 볼륨을 바꾸고 연주하려고 한다.

먼저, 공연이 시작하기 전에 각각의 곡이 시작하기 전에 바꿀 수 있는 볼륨의 리스트를 만들었다. 이 리스트를 V라고 했을 때, V[i]는 i번째 곡을 연주하기 전에 바꿀 수 있는 볼륨을 의미한다. 항상 리스트에 적힌 차이로만 볼륨을 바꿀 수 있다., 현재 볼륨이 P이고 지금 i번째 곡을 연주하기 전이라면, i번 곡은 P+V[i]나 P-V[i] 로 연주해야 한다. 하지만, 0보다 작은 값으로 볼륨을 바꾸거나, M보다 큰 값으로 볼륨을 바꿀 수 없다.

곡의 개수 N과 시작 볼륨 S, 그리고 M이 주어졌을 때, 마지막 곡을 연주할 수 있는 볼륨 중 최댓값을 구하는 프로그램을 작성하시오. 모든 곡은 리스트에 적힌 순서대로 연주해야 한다.

 Input

첫째 줄에 N, S, M이 주어진다. (1 ≤ N ≤ 100, 1 ≤ M ≤ 1000, 0 ≤ S ≤ M) 둘째 줄에는 각 곡이 시작하기 전에 줄 수 있는 볼륨의 차이가 주어진다. 이 값은 1보다 크거나 같고, M보다 작거나 같다.

 Output

첫째 줄에 가능한 마지막 곡의 볼륨 중 최댓값을 출력한다. 만약 마지막 곡을 연주할 수 없다면 (중간에 볼륨 조절을 할 수 없다면) -1을 출력한다.

 Solution

  • 이렇게 간단한 문제를 2일이나 풀었다.
  • 처음에 DP 배열 자체를 완전 잘못 정의해서 헤맸는데, 한참 헤매고 나니까 이제야 좀 감이 잡힌다. DP에서 Memoization기법을 사용하라는 말, 이전에 계산한 값을 저장하여 다시 계산하지 않는다는 말은 모든 데이터를 저장해야 한다는 것이 아니라, 정답이 될 수 있는 모든 수를 배열로 선언하고 그 수들에 대해서만 값을 갱신하는 것을 뜻한다.
  • 심지어 마지막 곡을 연주할 수 없다면 -1을 출력한다라는 조건을 까먹고 (너무 삽질을 해서…) 반례를 찾다가 또 시간을 허비했다.
  • 다음부터는 추천 문제 풀이시간 * 2를 넘어가면 바로 해답을 보자.
n, s, m = map(int, input().split())
vol = list(map(int, input().split()))
dp = [[False]*(m+1) for _ in range(n+1)]
dp[0][s] = True

for i in range(1,n+1):
    for j in range(m+1):
        if dp[i-1][j] ==0:
            continue
        if j+vol[i-1] <=m:
            dp[i][j+vol[i-1]] = True
        if j-vol[i-1] >=0:
            dp[i][j-vol[i-1]] = True

max = -1
for i,x in enumerate(dp[n]):
    if x != False:
        max = i

print(max)

 Feedback

  • 가변 인자
_list = [1, 2, 3, 4, 5]
first_index, *rest, last_index = _list
print(rest) # 2 3 4
  • Unpacking
_list = [1, 2, 3, 4, 5]
print(*_list) # 1 2 3 4 5
  • set을 활용할 수도 있다.
n,s,m=map(int,input().split())
l,d=[*map(int,input().split())],[s]
for i in l:
    d=[*set([j+i for j in d if j+i<=m]+[j-i for j in d if j-i>=0])]
print(max(d) if d else -1)

Source