LoginSignup
1
0

More than 3 years have passed since last update.

atcoder_E-Knapsack2を解いてみた

Posted at

概要

AtCoderのDPまとめコンテストのE問題を解いてみました。
解説はこちらの記事が分かりやすいと思いますが、いざ自分で実装するとなると中々手が動かせない。。。
そこで、記事の解説を図(手書き(;'∀'))で書いてみました。

解の方針

以下のように定義して、dpを順に更新していく。
詳しくはこちらの記事がやはり分かりやすいのでおススメです。

  • dp[ i ][ sum_v ] := i-1 番目までの品物から価値が sum_v 以上を達成するように選んだときの、重さの総和の最小値

イメージ図

さて、解の方針(概念)は分かってけど、いざ実装しようと思ったら手が止まる(;'∀')
そこで少しでも分かりやすくするため図に書いてみた。
dpcontest_E.jpg

コード

上の図を見ながらなんとか実装。。。

E-Knapsack2.py
#E問題
#https://atcoder.jp/contests/dp/tasks/dp_e
import numpy as np
N,W = map(int,input().split())
wvlist = [list(map(int,input().split())) for _ in range(N)]
INF = 10**15
ans = INF

#初期条件
dp = np.full((N+1,N*1000+1),INF)
dp[0][0] = 0

for i in range(N):
    #ここを普通の配列で2重ループで処理するとTLEになる。numpyの機能を使ってすばやく処理。
    dp[i+1][:wvlist[i][1]] = dp[i][:wvlist[i][1]]
    dp[i+1][wvlist[i][1]:] = np.minimum(dp[i][wvlist[i][1]:],dp[i][:-wvlist[i][1]]+wvlist[i][0])

for i in range(N*1000+1):
    if W >= dp[N][i]:
        ans = i

print(ans)

ちなみに、機能は満たしてるけど性能的にout(TLEになる)のがこちら
2重ループしてるとこが遅い。

E-Knapsack2(TLE).py
#あっているけど、実行時間超過
N,W = map(int,input().split())
#N,W = [3,8]
wvlist = [list(map(int,input().split())) for _ in range(N)]
INF = 10**15
ans = INF
#初期条件
dp = [[INF for _ in range(N*1000+1)] for i in range(N+1)]
#dp = np.full((N+1,N*1000+1),INF)
dp[0][0] = 0

for i in range(N):
    for v in range(N*1000+1):
        if v-wvlist[i][1]>=0:
            dp[i+1][v] = min(dp[i+1][v],dp[i][v-wvlist[i][1]]+wvlist[i][0])
        dp[i+1][v] = min(dp[i+1][v],dp[i][v])

for i in range(N*1000+1):
    if W >= dp[N][i]:
        ans = i

print(ans)

以上です。
DPの問題を解くときは、2次元配列の操作が難しくて図を描かないと解けません💦
いつか頭の中でできるようになりたいですねー(´・ω・`)

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0