トピック
回答
複数のバックパックの最適化:複数のバックパックのプレーンバージョンはO(nms)であり、この質問のデータ範囲は間違いなくタイムアウトになります
それは、最適化することができない
ことで、完全なナップザックの方法:式をリストすることによって、最後に余分な項目があることが見つかりませんし、完全なナップザックの数が無限大であるので、これ以上があるでしょうザ・。 f [i] [jv]の最大値は次のとおりです。f[i] [j]を更新できませんでした
バイナリ最適化:たとえば、i番目のアイテムを選択する場合、アイテムの数が30であるとします。バックパックの容量を超えていない場合は、0、1、2…30を選択して、状態方程式を更新できます。時間計算量あるO(S)。マジックはここにある。私たちは、一緒に2これらの30個の数字を入れて、バイナリを使用することができます0、2 1、2 2、2 3を、そして最後に15(2あり4彼らは合計を超えます= 16 30なので、最後に15を追加します)、つまり1、2、4、8、15(i番目のアイテムが非常に多くの部分に分割されてパッケージ化されている場合は、対応するボリュームと値にも対応するボリュームと値を掛ける必要があります値)、13 = 1 + 4 + 8などの0〜30の数値を考え出すことができるので、毎回この新しいグループを選択するかどうかを検討するだけで済みます。はい、これは完全に01ナップザックに変換されます。問題、時間複雑さはO(logs)になります
コード
#include<bits/stdc++.h>
using namespace std;
const int N = 25000;
int n, m, cnt;
int v[N], w[N];
int f[N];
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
int a, b, s; //体积,价值,个数
cin >> a >> b >> s;
int k = 1;
while (k <= s) {
cnt++; //分组后的下标
v[cnt] = a * k;
w[cnt] = b * k;
s -= k;
k *= 2;
}
if (s > 0) {
cnt++;
v[cnt] = a * s;
w[cnt] = b * s;
}
}
n = cnt;
//转化为01背包问题
for (int i = 1; i <= n; i++) {
for (int j = m; j >= v[i]; j--) {
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
}
cout << f[m] << endl;
return 0;
}