f
j
=
m
a
x
{
f
j
−
k
c
o
s
t
i
+
k
v
a
l
i
}
,
  
k
∈
[
0
,
c
o
u
n
t
i
]
\mathcal{f_j=max\{f_{j-kcost_i}+kval_i\},\;k\in[0,count_i]}
fj=max{fj−kcosti+kvali},k∈[0,counti]
做一点微小的工作
f
r
+
j
c
o
s
t
i
=
m
a
x
{
f
r
+
k
c
o
s
t
i
+
(
j
−
k
)
v
a
l
i
}
,
  
k
∈
[
j
−
c
o
u
n
t
i
,
j
]
\mathcal{f_{r+jcost_i}=max\{f_{r+kcost_i}+(j-k)val_i\},\;k\in[j-count_i,j]}
fr+jcosti=max{fr+kcosti+(j−k)vali},k∈[j−counti,j]
提成两部分
f
r
+
j
c
o
s
t
i
=
m
a
x
{
f
r
+
k
c
o
s
t
i
−
k
v
a
l
i
}
+
j
v
a
l
i
,
  
k
∈
[
j
−
c
o
u
n
t
i
,
j
]
\mathcal{f_{r+jcost_i}=max\{f_{r+kcost_i}-kval_i\}+jval_i,\;k\in[j-count_i,j]}
fr+jcosti=max{fr+kcosti−kvali}+jvali,k∈[j−counti,j]
由此。
枚举
r
\mathcal{r}
r,枚举
k
\mathcal{k}
k,单调队列。
当然这道题并不用优化(
*不要把题目给的东西的意义弄反
*不要忘记输出回车
*k-min(k,c)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cctype>
using namespace std;
int T, n, m;
int p, h, c;
int f[105];
pair<int, int> q[105];
int qt, qh;
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
for (int i = 0; i <= n; ++i) f[i] = 0;
for (int i = 1; i <= m; ++i) {
scanf("%d%d%d", &p, &h, &c);
for (int j = 0; j < p; ++j) {
qt = 0;
qh = 1;
for (int x, k = 0; /*qwq*/ ; ++k) {
if ((x = k * p + j) > n) break;
while (qh <= qt && q[qh].second < k - min(k, c)) ++qh;
while (qh <= qt && q[qt].first < f[x] - k * h) --qt;
q[++qt] = make_pair(f[x] - k * h, k);
f[x] = max(f[x], q[qh].first + k * h); //放在后面防止越界
}
}
}
printf("%d\n", f[n]);
}
return 0;
}