解説
一見すると,以下のような動的計画法(DP)で問題を解くことができそうです.
- dp[i][v]: i 番目までのプラモデルについて合計金額が v に等しいような購入の仕方は存在するか(存在するならば 1,そうでなければ 0 )
- dp[i−1][v]=1 ならば,dp[i][v+Ai]=dp[i][v+⌊1.01×Ai⌋]=1
この方針では,v は最大で N×max⌊1.01×Ai⌋ まで考える必要があるため,計算量は O(N2maxAi) となり制限時間に間に合いません.
ここで,通常版と限定版を選んだ場合の金額の差にのみ注目することで,上記のDPを以下のように改良します.
- dp[i][v]: i 番目までのプラモデルについて合計金額が A1+A2⋯+Ai+v に等しいような購入の仕方は存在するか
- dp[i−1][v]=1 ならば,dp[i][v]=dp[i][v+⌊0.01×Ai⌋]=1
こうすることで,v は最大で N×max⌊0.01×Ai⌋ まで考えれば十分です,
合計金額が K と等しくなるような購入の仕方が存在するかどうかは,S=A1+A2+⋯+AN として dp[N][K−S] から判定を行うことができます.
K−S の値が DP テーブルからはみ出してしまう場合には例外処理が必要ですが,答えは常に No
になります.
計算量は O(N2maxAi) から変わりませんが,定数倍が約 1001 になったことで問題を解くことができます.
なお,元の方針の DP でも,C++ の std::bitset
を用いて高速化すれば問題を解くことができます.