백준 2293 [python]

26644 단어 DP백준DP

https://www.acmicpc.net/problem/2293

DP를 풀 때 최적화된 풀이를 위한 점화식을 세우는데 더 공들여야겠다. 이상한 풀이로 시간 초과와 메모리 초과를 많이 당했다. 처음에 대충 생각해놓고 코드를 짜니 답이 없다. 더 집중해서 생각한 다음 코드를 적자.

ㅂㅅ코드1 (시간 초과)
이 코드는 동전을 돌며 세고 빼는 것을 반복해서 결국 0에 몇번 도달했냐를 계산한 후 0을 출력. 0은 k가 나눠지고 빼져서 k -> 0이 되었기 때문에 k가 한 번 만들어졌음을 의미. 엉망이다.

import sys

n, k = map(int, input().split())
coins = []
for i in range(n):
    coins.append(int(sys.stdin.readline()))
coins.sort(reverse=True)

res = [0 for i in range(10001)]
res[k] = 1

for coin in coins:
    temp_list = [i for i in range(10001) if res[i] != 0]
    for val in temp_list:
        for i in range(1, val // coin + 1):
            res[val - coin * i] += 1
print(res[0])

ㅂㅅ코드2 (시간 초과)
dp를 이차원 리스트로 하고 재귀함수로 dp값을 찾는 구조. find_dp 안의 점화식을 수정하면 시간 초과는 해결될 듯.

import sys

n, k = map(int, input().split())
coins = []
for i in range(n):
    coins.append(int(sys.stdin.readline()))
coins.sort()

dp = [[-1 for i in range(k + 1)] for i in range(n)]
for i in range(n):
    dp[i][0] = 1
for i in range(k + 1):
    if i % dp[0][i] == 0: dp[0][i] = 1
    else: dp[0][i] = 0

def find_dp(idx, val):
    if dp[idx][val] != -1: return dp[idx][val]
    sum = 0
    for i in range(val // coins[idx] + 1):
        sum += find_dp(idx - 1, val - i * coins[idx])
    dp[idx][val] = sum
    return sum

print(find_dp(n - 1, k))

ㅂㅅ코드3 (시간 초과)
위의 코드가 재귀함수를 사용했다면 이 코드는 for문으로 dp를 채우는 구조. 이것도 점화식이 잘못되어 시간 초과가 났다.

import sys

n, k = map(int, input().split())
coins = []
for i in range(n):
    coins.append(int(sys.stdin.readline()))
coins.sort()

dp = [[1 if i == 0 or (j == 0 and i % coins[0] == 0) else 0 for i in range(k + 1)] \
for j in range(n)]

for i in range(1, n):
    for j in range(coins[i]):
        dp[i][j] = dp[i - 1][j]
    for j in range(coins[i], k + 1):
        m = j
        while True:
            dp[i][j] += dp[i - 1][m]
            m -= coins[i]
            if m < 0: break 

print(dp[n - 1][k])

코드4 (메모리 초과)
엉망인 점화식을 고쳐서 이중for문에서 마무리되게 했다. 메모리 초과가 해결되기 위해서는 일차원 리스트 dp에 같은 방식으로 값을 덮어씌우면 된다.

import sys

n, k = map(int, input().split())
coins = []
for i in range(n):
    coins.append(int(sys.stdin.readline()))
coins.sort()

dp = [[1 if i == 0 or (j == 0 and i % coins[0] == 0) else 0 for i in range(k + 1)] \
for j in range(n)]

for i in range(1, n):
    for j in range(coins[i]):
        dp[i][j] = dp[i - 1][j]
    for j in range(coins[i], k + 1):
            dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i]]
            
print(dp[n - 1][k])

제출한 코드.

import sys

n, k = map(int, input().split())
coins = []
dp = [1 if i == 0 or i % coins[0] == 0 else 0 for i in range(k + 1)]
for i in range(n):
    coins.append(int(sys.stdin.readline()))
coins.sort()

for i in range(1, n):
    for j in range(coins[i], k + 1):
            dp[j] += dp[j - coins[i]]
            
print(dp[k])

코드를 쓰기 전에 맞는 풀이라는 확신이 들 때까지 사고하자.

좋은 웹페이지 즐겨찾기