题解
const N = 1010;
let v = new Int32Array(N);
let w = new Int32Array(N);
let s = new Int32Array(N);
let f = [];
let init = n => {
for (let i = 0; i <= n; i++) {
f[i] = new Int32Array(N);
}
}
let n = 0;
let buf = '';
process.stdin.on('readable', function () {
let chunk = process.stdin.read();
if (chunk) buf += chunk.toString();
});
let getInputNums = line => line.split(' ').filter(s => s !== '').map(x => parseInt(x));
let getInputStr = line => line.split(' ').filter(s => s !== '');
process.stdin.on('end', function () {
buf.split('\n').forEach(function (line, lineIdx) {
if (lineIdx === 0) {
n = getInputNums(line)[0];
m = getInputNums(line)[1];
init(n);
} else if (lineIdx <= n) {
let a = getInputNums(line)[0];
let b = getInputNums(line)[1];
let c = getInputNums(line)[2];
v[lineIdx] = a;
w[lineIdx] = b;
s[lineIdx] = c;
if (lineIdx === n) {
for (let i = 1; i <= n; i++) { //件数
for (let j = 0; j <= m; j++) { //体积
for (let k = 0; k <= s[i] && k * v[i] <= j; k++) //件数限制s,体积限制j
f[i][j] = Math.max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]);
}
}
console.log(f[n][m]);
}
}
});
});
尝试优化 (完全背包优化的方法)
https://pic1.zhimg.com/v2-38f85d0194edd03667a3fab400012890_b.png
这里相比于完全背包,多了最后一项,这是因为多重背包中有件数限制,f[i,j-v]最多只能减去s件,即j-v-sv = f - (s+1)v。因此此方法失败
优化
把限制的件数分解成若干份,每份只能使用一次(01背包)分解: 数量s = 1 + 2 +4 +…+剩下的数(最后一项凑不齐2的幂时,即为剩下的数)
题解
const N = 20000; //因为分组的原因,每个数量2000 被分为log2000 = 12
//再乘上原有物品种类12 * 2000 ,所以开20000
let v = new Int32Array(N);
let w = new Int32Array(N);
let s = new Int32Array(N);
let f = new Int32Array(N);
let n = 0;
let cnt = 0; //分组
let buf = '';
process.stdin.on('readable', function () {
let chunk = process.stdin.read();
if (chunk) buf += chunk.toString();
});
let getInputNums = line => line.split(' ').filter(s => s !== '').map(x => parseInt(x));
let getInputStr = line => line.split(' ').filter(s => s !== '');
process.stdin.on('end', function () {
buf.split('\n').forEach(function (line, lineIdx) {
if (lineIdx === 0) {
n = getInputNums(line)[0];
m = getInputNums(line)[1];
} else if (lineIdx <= n) {
let a = getInputNums(line)[0]; //体积
let b = getInputNums(line)[1]; //价值
let c = getInputNums(line)[2]; //数量
let k = 1;
while (k <= c) {
cnt++;
c -= k;
v[cnt] = a * k;
w[cnt] = b * k;
k *= 2;
}
if (c > 0) {
cnt++;
v[cnt] = a * c;
w[cnt] = b * c;
}
if (lineIdx === n) {
n = cnt; //物品数(包含数量不同的同类物品)
for (let i = 1; i <= n; i++) { //件数
for (let j = m; j >= v[i]; j--) { //体积
f[j] = Math.max(f[j], f[j - v[i]] + w[i]);
}
}
console.log(f[m]);
}
}
});
});