Johnny 成立了 Bytecomp,一个提供云计算能力的公司。这样的公司通常拥有许多快速计算机,客户可以在其上进行计算。
但是 Johnny 还没有购买任何计算机。于是他前往一家计算机商店,收到了包含全部 n n n 台可用的计算机的清单。
每台计算机都可以用三个属性描述:处理器的核心数量 c i c_i ci,时钟频率 f i f_i fi 以及价格 c i c_i ci。每台计算机包含 c i c_i ci 个不会互相干扰的核心,所以它们可以被分配给不同的任务。
当客户订购资源时,她会指定所需的核心数 C j C_j Cj 以及所需的最低时钟频率 F j F_j Fj,订单还包含客户愿意支付的价格 V j V_j Vj。
如果接受了一份订单,Bytecomp 需要提供对客户所需的算力的专用访问权。Johnny 需要选择 C i C_i Ci 个核心(可能来自不同的计算机),且它们的时钟频率至少为 F j F_j Fj,这些核心不能被分配给其它订单。
请你帮助 Johnny 赚取尽可能多的利润:接受一部分客户订单,并购买商店中的一部分计算机,以满足所有接受了的订单的需求。
你的目标是最大化总利润,即为客户提供算力的收入与购买计算机的成本之间的差值。
第一行一个整数 n n n( 1 ≤ n ≤ 1000 1 \leq n \leq 1000 1≤n≤1000),表示商店中可用的计算机的台数。
接下来 n n n 行,每行描述一台计算机,包含三个整数 c i , f i , v i c_i,f_i,v_i ci,fi,vi( 1 ≤ c i ≤ 50 1 \leq c_i \leq 50 1≤ci≤50, 1 ≤ f i ≤ 1 0 9 1 \leq f_i \leq 10^9 1≤fi≤109, 1 ≤ v i ≤ 1 0 9 1 \leq v_i \leq 10^9 1≤vi≤109),分别表示核心数,时钟频率和价格。
接下来一行一个整数 m m m( 1 ≤ m ≤ 1000 1 \leq m \leq 1000 1≤m≤1000),表示客户的订单总数。
接下来 m m m 行,每行描述一个订单,包含三个整数 C i , F i , V i C_i,F_i,V_i Ci,Fi,Vi( 1 ≤ C i ≤ 50 1 \leq C_i \leq 50 1≤Ci≤50, 1 ≤ F i ≤ 1 0 9 1 \leq F_i \leq 10^9 1≤Fi≤109, 1 ≤ V i ≤ 1 0 9 1 \leq V_i \leq 10^9 1≤Vi≤109),分别表示需要的核心数,最低时钟频率以及预算。
仅一行一个整数,表示能够获得的最大总利润。
4
4 2200 700
2 1800 10
20 2550 9999
4 2000 750
3
1 1500 300
6 1900 1500
3 2400 4550
350
此题很容易发现是01背包(选或不选),不妨把买的和卖的合为同一类型(将一些变量转负)。不过这道题细节很多,本蒟蒻交了十次才AC…请读者在阅读核心代码时仔细想一想边界。
#include
#include
#include
#include
#include
#define LL long long
using namespace std;
const int MAXN = 4005, MAXX = 100005;
const LL lmi = LONG_LONG_MIN;
struct Node {
int C, F, V;
}arr[MAXN];
int n, m, sum;
LL dp[MAXX];//剩余j个核心数的最大价值
bool vis[MAXX];
bool cmp(Node x, Node y) {
if(x.F != y.F) {
return x.F > y.F;
}
return x.V < y.V;
}
int main() {
LL ans = 0;
scanf("%d", &n);
for(int i = 1; i <= n; i ++) {
scanf("%d%d%d", &arr[i].C, &arr[i].F, &arr[i].V);
arr[i].V = -arr[i].V;
}
scanf("%d", &m);
for(int i = n + 1; i <= n + m; i ++) {
scanf("%d%d%d", &arr[i].C, &arr[i].F, &arr[i].V);
arr[i].C = -arr[i].C;
}
sort(arr + 1, arr + 1 + n + m, cmp);
for(int i = 1; i <= 100005; i ++) {
dp[i] = lmi;
}
vis[0] = 1;
for(int i = 1; i <= n + m; i ++) {
if(arr[i].V < 0) {
sum += arr[i].C;
for(int j = sum; j >= arr[i].C; j --) {
if(!vis[j - arr[i].C]) continue;
vis[j] |= vis[j - arr[i].C];
dp[j] = max(dp[j], dp[j - arr[i].C] + arr[i].V);
}
}
else {
for(int j = 0; j <= sum + arr[i].C; j ++) {
if(!vis[j - arr[i].C]) continue;
vis[j] |= vis[j - arr[i].C];
dp[j] = max(dp[j], dp[j - arr[i].C] + arr[i].V);
}
}
}
for(int i = 0; i <= sum; i ++) {
if(vis[i]) ans = max(ans, dp[i]);
}
printf("%lld", ans);
return 0;
}