题目链接
题解
非常简单的背包。
f
[
i
]
f[i]
f[i]表示购买
i
i
i个物品所需要最少的花费。
不考虑免费的限制条件,那么一定是选择前
k
k
k个双鞋子。
那么加入免费的条件,那么还是要挑最便宜的买。
g
[
i
]
g[i]
g[i]表示购买
i
i
i双鞋子能够免费最多的数量。
状态转移方程就是
f
[
i
]
=
m
i
n
(
f
[
i
]
,
f
[
j
]
+
c
a
l
c
(
i
,
j
)
)
f[i]=min(f[i],f[j]+calc(i,j))
f[i]=min(f[i],f[j]+calc(i,j)),其中
j
∈
[
1
,
i
)
j\in[1,i)
j∈[1,i)
把这个
c
a
l
c
(
i
,
j
)
calc(i,j)
calc(i,j)展开来就是
∑
k
=
j
+
1
i
a
[
k
]
−
∑
k
=
j
j
+
g
[
i
−
j
]
a
[
k
]
\sum^i_{k=j+1}a[k]-\sum^{j+g[i-j]}_{k=j}a[k]
∑k=j+1ia[k]−∑k=jj+g[i−j]a[k]
很明显这个式子可以用前缀和优化。
时间复杂度:
O
(
n
k
)
O(nk)
O(nk)
代码
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
namespace chhokmah {
#define N 200005
int f[N], g[N], a[N], sum[N];
int n, m, k;
void chhokmah() {
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i ++) sum[i] = sum[i - 1] + a[i];
for (int i = 1, x, y; i <= m; i ++) { scanf("%d%d", &x, &y); g[x] = max(g[x], y); }
for (int i = 1; i <= k; i ++) {
f[i] = inf;
for (int j = 0; j < i; j ++) f[i] = min(f[i], f[j] + sum[i] - sum[j + g[i - j]]);
}
cout << f[k] << endl;
} }
int main() { chhokmah::chhokmah(); return 0; }