传送门: 小 A 的卡牌游戏 - Gym 103186B - Virtual Judge
小 A 最近沉迷于一款名为 Hearthverse 的卡牌游戏。在这款游戏中,卡被分为了三个种类(随从、法术和魔法阵),在组卡时,这款游戏严格规定了卡组中每种卡牌的数量,具体来说,一副 nn 张卡的卡组需要包含恰好 aa 张随从卡, bb 张法术卡和 cc 张魔法阵卡,并且 a + b + c = na+b+c=n。
在游戏中,有一个叫做 "3pick" 的组卡竞技方式,游戏会给出 nn 次三选一的机会,三张卡分别来自三个种类。每次玩家需要从三张卡中选出一张卡加入自己的卡组。为了使卡组强度尽量高,小 A 给每张卡设定了一个强度值,而卡组的强度就是所有卡强度值的和,他希望他最后组出的卡组的强度可以尽量高。
Input
第一行有四个整数 n, a, b, cn,a,b,c (1\leq a, b, c\leq n \leq 5000, a+ b + c = n1≤a,b,c≤n≤5000,a+b+c=n),分别表示卡组的总卡数与每种种类的卡的张数要求。
接下来 nn 行,每行代表一次 "3pick" 的机会,第 ii 行有三个整数 a_i,b_i,c_iai,bi,ci (1 \leq a_i,b_i,c_i \leq 10^91≤ai,bi,ci≤109) 分别表示这一次选择中随从卡、法术卡和魔法阵卡的强度值。
Output
在一行输出一个整数,表示 小 A 能组出的卡组的最大强度值。
Examples
Input
3 1 1 1 4 1 6 1 1 10 5 7 4Output
21Input
6 3 2 1 1000000000 1 1 1000000000 1 1 1000000000 1 1 1 1000000000 1 1 1000000000 1 1 1 1000000000Output
6000000000
训练赛时傻傻的写了一个tle的代码,当发现开不了三维数组想到了降维,但以为用map代替可以过服气,想想当时傻傻的用直接搜。当然这也挺好的,也学会了另外一种降维方式,那么总结下现在接触到的降维方式1,当只有两个数,选一个就不选另一个那种就可以只计算其中一个。2就是这里的贪心降维。相同点就是两个方式都是第一维记录的是总数,第二维记录的是某个数的值。
当时训练赛时我也想过降维的,当是怎么说降维时想不到a, b怎么处理,开了题解之后才发现能够用贪心处理。确实当只有a和b时,只要a与b的差值越大那我们我们会优先选择大的那个数。
代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define ll long long
const int N = 5010;
ll dp[N][N];
struct Node {
int a, b, c;
}node[N];
bool cmp(Node &a, Node &b) {
return a.a - a.b > b.a - b.b;
}
int main() {
int n, a, b, c;
cin >> n >> a >> b >> c;
for (int i = 1; i <= n; i++) cin >> node[i].a >> node[i].b >> node[i].c;
sort(node + 1, node + n + 1, cmp);
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= i; j++) {
if (j) dp[i][j] = dp[i - 1][j - 1] + node[i].c;
if (j == i) continue;
if (i - j <= a) dp[i][j] = max(dp[i][j], dp[i - 1][j] + node[i].a);
else dp[i][j] = max(dp[i][j], dp[i - 1][j] + node[i].b);
}
}
cout << dp[n][c];
return 0;
}