Solution - [CEOI2018]Cloud computing

思路

首先考虑贪心,按 \(f\) 进行从小到大排序。特别的,当 \(f\) 相等时,就按价格进行排序。

然后我们就可以用类似 01 背包的方法,为了方便,我们可以将计算机的价格置为负数。定义状态 \(dp_j\) 表示内核数为 \(j\) 时所得的最大利润。背包容量即为所购买的计算机内核的总和 \(tot\)。

所以状态转移方程即为

\[dp_{j+c_i}\gets \max dp_{j+c_i}, dp_j+v_i \]

这里要注意的是,当处理的是计算机时需要倒叙枚举,反正则倒叙

时间复杂度 \(O((n+m)\displaystyle\sum_{i=1}^n p_i)\)

Code.

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, m;
struct node {
	int c, f, v;
} a[4005];
bool cmp(node x, node y) {
	return x.f == y.f ? x.v < y.v : x.f > y.f;
}
int dp[200005], tot;
signed main() {
    scanf("%lld", &n);
    for (int i = 1; i <= n; i++) {
    	scanf("%lld %lld %lld", &a[i].c, &a[i].f, &a[i].v);
    	a[i].v *= -1;
	}
	scanf("%lld", &m);
	for (int i = n + 1; i <= m + n; i++) {
		scanf("%lld %lld %lld", &a[i].c, &a[i].f, &a[i].v);
	}
	sort(a + 1, a + n + m + 1, cmp);
	memset(dp, 128, sizeof(dp));
	dp[0] = 0;
	for (int i = 1; i <= n + m; i++) {
		if (a[i].v < 0) {
			for (int j = tot; j >= 0; j--) dp[j + a[i].c] = max(dp[j + a[i].c], dp[j] + a[i].v);
			tot += a[i].c;
		} else {
            for (int j = 0; j <= tot; ++j) dp[j] = max(dp[j], dp[j + a[i].c] + a[i].v);
        }
	}
	int ans = 0;
	for (int i = 0; i <= tot; i++) {
		ans = max(ans, dp[i]);
	}
	printf("%lld", ans);
    return 0;
}
上一篇:STL之Set


下一篇:人类智慧贪心