13024: 【原3024】有限背包
题目
题目描述
author: snow_sword 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/3024
Description
大家都已经学过了01背包问题,现在这个问题稍微有一些变化:第i种物品可能有pi个,你可以选取任意个(小于pi)。给定背包容量m,求背包能达到的最大价值。
Input Format
第1行有2个整数n, m,表示要有n种物品,背包容量为m 第2到n+1行,每行三个整数pi, wi, vi,分别表示该种物品有pi个,每个物品重wi,价值为vi
Output Format
输出一个数字, 表示背包能达到的最大价值。
Sample Input 1
4
3 9
1 2 3
2 3 4
3 4 5
Sample Output1
12
数据范围
对于80%的数据,1<=n<=1000,1<=m<=1000, 1<=sumP=p1+p2+...+pn<=2000 对于100%的数据,1<=N<=1000, 1<=m<=1000, 1<=pi<=1000
yyong119's solution
#include<cstdio>
#include<cstring>
#include<algorithm>
#include <deque>
#define MAX_N 1010
using namespace std;
int n, m;
int f[MAX_N];
int p[MAX_N], w[MAX_N], v[MAX_N];
deque<int> x, y;
void solve() {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < w[i]; ++j){
x.clear(); y.clear();
for (int k = 0; j + w[i] * k <= m; ++k) {
int we = j + w[i] * k, va = v[i] * k;
if (x.size() == p[i] + 1) {
if (y.front() == x.front())
y.pop_front();
x.pop_front();
}
int t = f[we] - va;
x.push_back(t);
while (!y.empty() && t >= y.back())
y.pop_back();
y.push_back(t);
f[we] = y.front() + va;
}
}
}
}
int main() {
scanf("%d%d", &n, &m);
memset(f, 0, sizeof(f));
for (int i = 0; i < n; ++i)
scanf("%d%d%d", &p[i], &w[i], &v[i]);
solve();
printf("%d\n", f[m]);
return 0;
}