HDU 2844 Coins 多重背包

该题是母函数的变种,也是一种多重背包问题,由于写了几篇这样的,所以就不重累述了,如果不懂可以看一下背包九讲;

#include<stdio.h>

#include<stdlib.h>

int CompletePack( int f[],int val,int money ,int sum)//完全背包

{

     for( int i=val; i<=money;i++ )

     {

           if( i>=val&&f[ i-val ]+val>f[i] )

           {

             f[i]=f[i-val]+val;

             if( f[ i ]==i )//如果相等,则代表有这种情况

             {

             sum++; 

             }

            }  

     }

     return sum;     

}

int ZeroOnePack( int f[],int n,int val,int money,int sum  )//01背包

{

     int t=n*val;

    for( int i=money; i>=t; i-- )

       if( i>=t&& f[ i-t ]+t>f[i])

       {

          f[ i ] = f[i-t] +t;

          if( f[i]==i )//如果相等,则代表有这种情况

          {

          sum++; 

          } 

       }

       return sum; 

}

int DP( int val[],int num[], int n, int money )

{

    int f[100024]={0},sum=0;

    for( int i=1; i<=n; i++ )

    {

         if( num[i]*val[i]>=money )

           sum=CompletePack( f,val[i],money,sum );

          else 

          {

              int k=1,count=num[i];

              while( k<count )

              {

                   sum=ZeroOnePack( f,k,val[i] ,money,sum);

                     count=count-k;

                     k=k<<1;      

              }

              sum=ZeroOnePack( f,count,val[i] ,money,sum);     

          }   

    }

    return sum;    

}

int main()

{

   int n,money,val[124],num[124];

   while( scanf( "%d%d",&n,&money ),n||money )

   {

      for( int i=1; i<=n; i++ )

        scanf( "%d",&val[i] );

      for( int i=1; i<=n; i++ )

        scanf( "%d",&num[ i ] );

       printf( "%d\n",DP( val, num, n,money ) );       

   }

   return 0;    

}

  

你可能感兴趣的:(HDU)