这道题相比上个多重背包,数据范围扩大,直接遍历各个物品的数量会TLE,这个地方用到一个巧妙地优化方法:二进制。
例如1,2,4,8,16,…
16以内的正整数能用20 21 22 23 凑出来,所以把物品打包来处理,不会遗漏任何数字。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter pw = new PrintWriter(System.out);
static int N = 2010;
static int n, m;
static int f[] = new int[N];
static ArrayList<Good> al = new ArrayList<>();
public static void main(String[] args) throws IOException {
String[] s = br.readLine().split(" ");
n = Integer.parseInt(s[0]);
m = Integer.parseInt(s[1]);
for (int i = 0; i < n; i++) {
s = br.readLine().split(" ");
int w = Integer.parseInt(s[0]);
int v = Integer.parseInt(s[1]);
int c = Integer.parseInt(s[2]);
for (int k = 1; k <= c; k *= 2) {
c -= k;
al.add(new Good(k * w, k * v));
}
if (c > 0) al.add(new Good(c * w, c * v));
}
for (Good g : al) {
for (int i = m; i >= 0; i--)
if (i >= g.getW())
f[i] = Math.max(f[i], f[i - g.getW()] + g.getV());
}
pw.println(f[m]);
pw.flush();
pw.close();
br.close();
}
}
class Good {
int w;
int v;
public Good(int w, int v) {
this.w = w;
this.v = v;
}
public int getW() {
return w;
}
public void setW(int w) {
this.w = w;
}
public int getV() {
return v;
}
public void setV(int v) {
this.v = v;
}
}