这道题很有意思,N,C的数据量达到10000,如果用普通的01背包来做绝对会超时,注意到v和c只有0~10的范围,这说明有大量的v,c是重复的,相同的v,c的单词是等价的,这样就可以转化为多重背包来做。
不过普通的多重背包又可能会超时,于是我们采取二进制优化的方式来优化成01背包问题。
从01背包到多重背包又到01背包,的确是道好题。。
#include <bits/stdc++.h>
using namespace std;
char in[20];
const int N = 100000+10;
int v[N],c[N],st[15][15],dp[N];
int main()
{
int num,C;
while(~scanf("%d %d",&num,&C))
{
memset(v, 0, sizeof(v));
memset(c, 0, sizeof(c));
memset(st, 0, sizeof(st));
memset(dp, 0, sizeof(dp));
int cnt = 0,cp,va;
for(int i = 1; i <= num; i++)
{
scanf("%s %d %d",in, &va, &cp);
st[va][cp]++;
}
for(int i = 0; i <= 10; i++)//二进制优化 不太熟
{
for(int j = 0; j <= 10; j++)
{
if(st[i][j])
{
int temp = 1;
while(st[i][j] > temp)
{
++cnt;
v[cnt] = temp * i;
c[cnt] = temp * j;
st[i][j] -= temp;
temp = temp << 1;
}
++cnt;
v[cnt] = st[i][j] * i;
c[cnt] = st[i][j] * j;
}
}
}
for(int i = 1; i <= cnt; i++)
{
for(int j = C; j >= c[i]; j--)
{
dp[j] = max(dp[j], dp[j - c[i]] + v[i]);
}
}
cout << dp[C] << endl;
}
return 0;
}