LeeBlog

导航

HDU 2844 Coins 多重背包

这题看着我第一感觉是母函数,但是据说母函数会TLE,就果断多重背包了,而这里用多重背包做,明显不能直接把dp[n]输出来,那样结果是错的,那怎么才能找到种类呢。if( dp[i] )  ++c;??????这样行吗???? 不行,这是后要想到dp[i]的含义,dp[i]代表着在重量i时能找到的最大价值,而这里的重量和价值都是钱,所以就有很方便的一个地方了,dp[i]中最多能装下i的话那么肯定i能够选到,所以就有判断条件了if( dp[i] == i ) ++c;

直接上代码吧

#include<stdio.h>
#include<string.h>
//#define max( a , b )  ( a ) > ( b ) ? ( a ) : b
int n,m,v[105],w[105],num[105],dp[100005];
inline int max( int a,int b )//记得加内联,这样要快很多很多
{
    return a > b ? a : b;
}
void _01( int v, int w )
{
     for( int j = m; j >= v; --j )
          dp[j] = max( dp[j-v] + w, dp[j] );
 }
void complete( int v,int w )
{
     for( int j = v; j <= m; ++j )
          dp[j] = max( dp[j-v] + w, dp[j] );
 }
void multiply( int v,int w,int c )
{
     if( v * c > m )
         complete( v,w );
     else
     {
         int k = 1;
         while( c > k )
         {
                _01( k * v, k * w );
                c -= k;
                k <<= 1;
                }
         _01( c * v, c * w );
     }
 }
int main( )
{
    while( scanf( "%d%d",&n,&m ),n|m )
    {
           for( int i = 1; i <= n; ++i )
                scanf( "%d",&v[i] );
           for( int i = 1; i <= n; ++i )
                scanf( "%d",&num[i] );
           memset( dp,0,sizeof( dp ) );
           for( int i = 1; i <= n; ++i )
                multiply( v[i],v[i],num[i] );
           int c = 0;
           for( int i = 1; i <= m; ++i )
                if( dp[i] == i )
                    ++c;
           printf( "%d\n",c );
           }
    return 0;
}

posted on 2011-05-18 10:51  LeeBlog  阅读(187)  评论(0编辑  收藏  举报