リンク
https://codeforces.com/contest/808/problem/E
問題概要
ただ制約が特殊
解法
い つ も の dp[i]:iの重さを持つ時の価値の最大値,というDPは計算量がO(NM)になってしまい間に合わない。
明らかに怪しい制約があるのでそれを生かす方向性で考える。
これと似た問題をAtCoderで前やったなぁと思ったけどその問題を思い出せず・・・
思い出しました D - Simple Knapsack
v=1,v=2,v=3となるものを選ぶ個数をそれぞれ,a,b,c個とすると、を満たせば良く、このうち変数を2個固定させれば残りの1個は取れるだけ貪欲に取るのが最善になる。
dp[i]:i以下の重さを詰めた時の価値の最大値、その時のa,bの値
としてdp配列の情報を持たせてあげればいつものようなDPをすることによって遷移させていくことが出来る。
実装
感想
こういうDPバグらせずに一発で書けるの偉いな、と思った(自分に甘い)
追記(2020/1/5)
dp[i]から向かう遷移先としてdp[i+1],dp[i+2]として良いのか、という正当性の議論があった。
Educational Codeforces Round 21 — Editorial - Codeforces
多分解説としては一番これがわかりやすい
一応当時のTLの様子も貼っておきます。
この解法すごいなーと思ったんだけど、実は僕はまだ理解できていません。。dp[i] が dp[i-2] や dp[i-1] から遷移することって証明できるのかな。(まだ頭が混乱している)
— tarattata (@tarattata1) 2020年1月3日
Knapsack DP において重みが 1, 2, 3 の 3 種類しかないときに 1, 2 をいくつ使ったかを覚えながら DP して 3 を貪欲に入れるって書いてあるんだけどこれなんでできるんですか? https://t.co/QgKOcBJ3IH
— tsutaj (@tsutaj) 2020年1月4日
-
この追記をした思い立ち
コンテスト直後に誰かがぼそっと書いてRT/likeされまくるけど、数ヶ月後にみんな忘れて検索にも引っかからなくて発掘不可能になってる有用な知見いっぱいありそう
— アルメリア (@armeria_betrue) 2020年1月4日