「CF1154F」Shovels Shop【背包DP】

题目链接

【洛谷传送门】

题解

非常简单的背包。
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[ij]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; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值