这题一看就是个背包题目,01背包种类n,容量c
可是n和c太大了,那样o(nc)肯定超时。
其实这题的什么单词根本无所谓了,我们只关心它的c和v,而且c和v都<=10,也就是c和v的组合最多只有100种
只要c和v一样,我们就看做一种物品,数量+1,这样就转化成多重背包问题了,物品种类不超过100,利用二进制优化。
代码:
#include<stdio.h>
#include<string.h>
int dp[10010],num[11][11],cost[110],val[110],count[110];
int vat[11][11],vac[11][11];
char str[15];
int Max(int a,int b)
{
return a>b?a:b;
}
void Completepack(int co,int va,int m)
{
int i;
for(i=co;i<=m;i++)
dp[i]=Max(dp[i-co]+va,dp[i]);
}
void Zeronepackage(int co,int va,int m)
{
int i;
for(i=m;i>=co;i--)
dp[i]=Max(dp[i-co]+va,dp[i]);
}
int main()
{
int n,c,va,co,m;
int i,j,k;
while(scanf("%d%d",&n,&c)!=EOF)
{
memset(dp,0,sizeof(dp));
memset(num,0,sizeof(num));
memset(cost,0,sizeof(cost));
memset(val,0,sizeof(val));
memset(count,0,sizeof(count));
memset(vat,0,sizeof(vat));
memset(vac,0,sizeof(vac));
for(i=0;i<n;i++)
{
scanf("%s%d%d",&str,&va,&co);
num[va][co]++;
vat[va][co]=va;
vac[va][co]=co;
}
m=0;
for(i=0;i<11;i++)
{
for(j=0;j<11;j++)
if(num[i][j]>0)
{
val[m]=vat[i][j];
cost[m]=vac[i][j];
count[m]=num[i][j];
m++;
}
}
for(i=0;i<m;i++)
{
if(count[i]*cost[i]>c)
Completepack(cost[i],val[i],c);
else
{
k=1;
while(k<count[i])
{
Zeronepackage(k*cost[i],k*val[i],c);
count[i]-=k;
k=k*2;
}
Zeronepackage(count[i]*cost[i],count[i]*val[i],c);
}
}
printf("%d\n",dp[c]);
}
return 0;
}