AcWing 6. java版本的单调队列实现多重背包问题
原题链接
困难
作者:
Hysterical
,
2020-02-11 17:51:23
,
所有人可见
,
阅读 2
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 表示物品种类
int n = scan.nextInt();
// 表示 最大的容积
int V = scan.nextInt();
int[] dp = new int[V + 1];
for (int i = 0; i < n; i++) {
int v = scan.nextInt();
int w = scan.nextInt();
int s = scan.nextInt();
int[] pre = Arrays.copyOf(dp,dp.length);
// 遍历所有余数
for (int j = 0; j < v; j++) {
// 每个余数对应一个双端队列,实现单调队列
LinkedList<Integer> queue = new LinkedList();
for (int k = j; k <= V; k = k + v) {
// 1. 去除队尾不符合要求的,保证从大到小,如果前面数小则需要依次弹出
while (!queue.isEmpty() && pre[queue.peekLast()] - (queue.peekLast() - j) / v * w <= pre[k] - (k - j) / v * w) {
queue.pollLast();
}
// 2.判断当前队列中队首的值是否有效
if (!queue.isEmpty() && queue.peek() < k - s * v) {
queue.poll();
}
// 3.添加当前值对应的数组下标
queue.addLast(k);
// 4.拿到队首最大值
dp[k] = Math.max(dp[k], pre[queue.peek()] + (k - queue.peek()) / v * w);
}
}
}
System.out.println(dp[V]);
}
}