把朴素多重背包的式子稍作转化,得到:
f
j
=
m
a
x
{
f
k
′
−
k
′
v
a
l
u
e
  
∣
  
k
′
∈
[
j
′
−
c
o
u
n
t
i
,
j
′
]
}
+
j
′
v
a
l
u
e
,
  
j
′
c
o
s
t
i
+
R
e
m
a
i
n
d
e
r
=
j
\mathcal{f_{j}=max\{f_{k'}-k'value\;|\;k'\in[j'-count_i,j']\}+j'value,\;j'cost_i+Remainder=j}
fj=max{fk′−k′value∣k′∈[j′−counti,j′]}+j′value,j′costi+Remainder=j(枚举
R
e
m
a
i
n
d
e
r
\mathcal{Remainder}
Remainder)
看了半天感觉不太对结果发现这道题也是代价等于价值,,
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
int n, m;
int a[205];
int c[205];
pair<int, int> q[20005];
int qh, qt;
int f[20005];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
for (int i = 1; i <= n; ++i) {
scanf("%d", &c[i]);
}
scanf("%d", &m);
memset(f, 0x3f, sizeof(f));
f[0] = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j < a[i]; ++j) {
qh = 1;
qt = 0;
for (int x, k = 0; ; ++k) {
if ((x = k * a[i] + j) > m) break;
while (qh <= qt && q[qh].second < k - c[i]) {
++qh;
}
while (qh <= qt && q[qt].first >= f[x] - k) {
--qt;
}
q[++qt] = make_pair(f[x] - k, k);
f[x] = min(f[x], q[qh].first + k);
}
}
}
printf("%d", f[m]);
return 0;
}