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背包选择哪袋米选还是不选,代码如下