直接 DP 的话肯定超时
因为每个单词的 Complex 和 Value 都不会超过 10
所以里面肯定存在大量的相同价值的物品
将相同价值的物品合并后用多重背包解之即可
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define BUG puts("HERE!")
using namespace std;
const int MAX = 1e5 + 5;
const int INF = 0x7fffff;
int cnt, num, dp[MAX];
int n, m;
struct th{
int v, c, n;
bool operator != (const th& a) const{
return v != a.v || c != a.c;
}
bool operator < (const th& a) const{
if(c != a.c)
return c < a.c;
return v > a.v;
}
}a[MAX];
void init(){
for(int i = 0; i <= n; ++i)
a[i].n = 0;
cnt = 0, num = 1;
memset(dp, 0, sizeof(dp));
}
void zop(int c, int v){
for(int i = m; i >= c; --i)
dp[i] = max(dp[i], dp[i - c] + v);
}
void cp(int c, int v){
for(int i = c; i <= m; ++i)
dp[i] = max(dp[i], dp[i - c] + v);
}
void mp(int c, int v, int a){
if(c * a >= m){
cp(c, v);
return;
}
for(int i = 1; i <= a; a -= i, i <<= 1)
zop(c * i, v * i);
zop(c * a, v * a);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
#endif
int c, tv, tc;
char s[22];
while(~scanf("%d%d", &n, &m)){
for(int i = 0; i < n; ++i)
scanf("%s%d%d", s, &a[i].v, &a[i].c);
sort(a, a + n);
init();
for(int i = 0; i < n; ++i)
if(i == n - 1 || a[i] != a[i + 1])
a[cnt] = a[i], a[cnt].n = num, num = 1, cnt++;
else
num ++;
for(int i = 0; i < cnt; ++i)
mp(a[i].c, a[i].v, a[i].n);
printf("%d\n", dp[m]);
}
return 0;
}