HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
http://acm.hdu.edu.cn/showproblem.php?pid=2191
#include<stdio.h>
#include<stdlib.h>
void CompletePack( int price,int f[],int money,int weight )//完全背包
{
for( int i=price; i<=money; i++ )
{
if( f[ i-price ]+weight>f[i] )
{
f[i]=f[i-price] + weight;
}
}
}
void ZeroOnePack( int price,int num,int f[],int money,int weight )//01背包
{
int t=num*weight,tt=num*price;
for( int i=money; i>=tt;i-- )
{
if( f[ i-tt ]+t > f[i] )
{
f[i]=f[i-tt]+t;
}
}
}
int DP( int price[],int weight[],int num[],int number ,int money)
{
int f[124]={0};
for( int i=1; i<=number ; i++ )
{
if( price[i]*num[i]>= money)
{
CompletePack( price[i],f,money,weight[i] );
}
else
{
int k=1;
while( k<num[i] ) //2进制法
{
ZeroOnePack( price[i],k,f,money,weight[i] );
num[i]=num[i]-k;
k=k<<1;
}
ZeroOnePack( price[i],num[i],f,money,weight[i] );
}
}
return f[money];
}
int main()
{
int money,n,number,price[124],num[124],weight[124];
scanf( "%d",&n );
for( int i=0; i<n; i++ )
{
scanf( "%d%d",&money,&number );
for( int j=1; j<=number ; j++ )
{
scanf( "%d%d%d",&price[j],&weight[j],&num[j] );
}
printf( "%d\n",DP( price,weight,num,number,money ) );
}
return 0;
}
该题是要用一定的钱买米(钱不一定要用完),而米的数量是确定的,因此该题是一个多重背包问题,主要要处理的问题是米的数量与钱的问题,
米的价钱与数量的乘积大于钱数时,代表该种米是足量的,可以用多完全背包解,当小于钱数时,代表该种米时不足够的,那么我们只能用01背包选择哪袋米选还是不选,代码如下

浙公网安备 33010602011771号