题目大意:给你N个字符串(N<100000),以及上限复杂度C(C<100000),每个字符串的价值为v[i],复杂度为c[i],(0<=v[i],c[i]<=10)现在要求在总复杂度和不超过C的情况下得到尽量大的价值。
考察点:DP
思路分析:虽然一眼就知道是个01背包,但是一开始看到N和C的范围傻眼了。。后来再看c[i]跟v[i]的范围,可以发现这其中肯定有大量重复的,所以01背包就转变成多重背包啦
#include<stdio.h>
#define max(x,y) (x)>(y)? (x):(y)
int c[15][15];
int f[10010];
char str[21];
int t,m,n;
void zeroonepack(int x,int y)
{
int i;
for (i=m;i>=x;i--)
f[i]=max(f[i],f[i-x]+y);
}
void complepack(int x,int y)
{
int i;
for (i=x;i<=m;i++)
f[i]=max(f[i],f[i-x]+y);
}
void multiplepack(int x,int y,int z)
{
if (x*z>=m) complepack(x,y);
else {
int k=1;
while (k<z)
{
zeroonepack(x*k,y*k);
z=z-k;
k=k*2;
}
zeroonepack(z*x,z*y);
}
}
int main()
{
int i,j,x,y;
while(scanf("%d%d",&t,&m)!=EOF)
{
memset(f,0,sizeof(f));
memset(c,0,sizeof(c));
n=0;
for (i=1;i<=t;i++)
{
scanf("%s%d%d",str,&x,&y);
c[x][y]++;
}
for (i=0;i<=10;i++)
for (j=0;j<=10;j++)
if (c[i][j]!=0)
multiplepack(j,i,c[i][j]);
printf("%d\n",f[m]);
}
return 0;
}