01バックパックのスペース最適化
01バックパックを学ぶとき、そのような状態遷移方程式があります:
约定:
dp[i][j]表示在0~i下标物品中选取,在总金额不超过j的情况下获得的最大价值
v[i]表示第 i 下标的物品的价值
dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]]+v[i]);
dp[i-1][j]
[i下付き]を選択しない項目に
dp[i-1][j-v[i]]+v[i]
対応[i下付き]を選択しない項目に対応
再帰的な数式をすばやく書くことができます
maxPrice表示考虑的最大总金额
共有 0~n-1 下标共n件物品
for(int i=0; i<n; i++)
for(int j=0; j<=maxPrice; j++)
dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]]+v[i]);
現在のグリッドの回答は上一行0~j下标的格子
関係があるだけであることがわかります。
次に、1つの行を保存するだけでよく、問題は前の行jと前の領域に起因します。前の行を確実に取得できるように、jを減少形式で更新する必要があります。前の値(jが減少して更新されるため、前が古い値なので、前の行の古い値が必要です)
図:添字考慮すると、新しい更新された値、古い赤のライン値、ブルーパフォーマンス0~i-1
場合は、
その後、簡素化状態空間に転送することができます
for(int i=0; i<n; i++)
for(int j=maxPrice; j>=0; j--)
dp[j] = max(dp[j], dp[j-v[i]]+v[i]);
完全なバックパック時間の最適化
完全なバックパックは01バックパックに似ていますが、各アイテムを無数に選択できるので、01バックパックに基づく状態遷移をすばやく書き込むことができます。
约定:
dp[i][j]表示在0~i下标物品中选取,在总金额不超过j的情况下获得的最大价值
共有 0~n-1 下标共n件物品
maxPrice表示考虑的最大总金额
v[i]表示第 i 下标的物品的价值
k表示第i下标的物品,选取k件
for(int i=0; i<n; i++)
for(int j=0; j<=maxPrice; j++)
for(int k=0; j-k*v[i]>=0; k++)
dp[i][j] = max(dp[i-1][j], dp[i-1][j-k*v[i]]+k*v[i]);
i番目のインデックスアイテムを選択する可能性を列挙し、01バックパックを複数回実行して最大の結果を取得しますが、これにより時間のオーバーヘッドが増加します。kサイクルを削除する方法はありますか?
【で0~i
選択添字アイテム、Jを超えない合計量の場合に得られた最大値]は、実際には、問題が思うことがあります。
同じアイテムを無数に取ることができる場合、問題は次のようになります。
- 【で
0~i-1
選択添字項目、総量の場合に得られた最大値Jを超えません] - 【で
0~i
その試み複数の選択肢の一方の選択された添字アイテム、JVを超えない合計量の場合に得られた最大値[I]
質問1は前の行の値です。問題ありません。質問2はこの行の右側の値です。jが段階的に更新されるため、質問2に対する最良の回答がちょうど行われたことがすぐにわかります。この行左側では、すぐに最適化できます
問題1の解決策が赤い領域であり、問題2の解決策が黄色の領域であると仮定します。
约定:
dp[i][j]表示在0~i下标物品中选取,在总金额不超过j的情况下获得的最大价值
共有 0~n-1 下标共n件物品
maxPrice表示考虑的最大总金额
v[i]表示第 i 下标的物品的价值
for(int i=0; i<n; i++)
for(int j=0; j<=maxPrice; j++)
dp[i][j] = max(dp[i-1][j], dp[i][j-v[i]]+v[i]);
kを列挙するには?つまり、複数のアイテムが選択されていることを確認するにはどうすればよいですか?
dp[i][j-v[i]]
の値は、dp配列によって定義され、すでに複数のiアイテムの選択を検討した結果であり、すでに最適な答え(kアイテムを選択する場合があります)に基づいてiアイテムを追加して、増加を試みます。より大きな結果が得られるかどうかを確認するiアイテム
01バックパックのスペース最適化に基づくこともできます。ここにスペース最適化のコードを示します。このコードは、jループの方向が変更のために送信されることを除いて、01バックパックのスペース最適化と非常に似ています。
for(int i=0; i<n; i++)
for(int j=0; j<=maxPrice; j++)
dp[j] = max(dp[j], dp[j-v[i]]+v[i]);