hdu 3732
题目中n和C的范围为100000,很庞大,如果直接用01背包,会超时
考虑到每个的v和c的范围在10以下,可以采用二进制优化,
用mapp[i][j]记录价值为i,体积为j的个数
最后转化为多重背包求解
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#define INF 99999999
using namespace std;
int main()
{
int n,C;//个数,总体积
char s[1001];
int V[100010];
int Z[100010];
int dp[10010];
int mapp[11][11];//记录价值与体积对应时的个数
int cnt,v,c;
while(scanf("%d %d",&n,&C)!=EOF)
{
memset(mapp,0,sizeof(mapp));
for(int i=0;i<n;i++)
{
scanf("%s %d %d",s,&v,&c);
mapp[v][c]++;
}
cnt=0;
for(int i=1;i<=10;i++)
{
for(int j=1;j<=10;j++)
{
for(int k=1;;k*=2)
{
if(mapp[i][j]>0)
{
if(mapp[i][j]>=k)
{
V[cnt]=k*i;Z[cnt]=k*j;mapp[i][j]-=k;cnt++;
}
else
{
V[cnt]=mapp[i][j]*i;Z[cnt]=mapp[i][j]*j;cnt++;
break;
}
}
else
break;
}
}
}
memset(dp,0,sizeof(dp));
for(int i=0;i<cnt;i++)
{
for(int j=C;j>=Z[i];j--)
dp[j]=max(dp[j],dp[j-Z[i]]+V[i]);
}
printf("%d\n",dp[C]);
}
return 0;
}