HDU 2602 Bone Collector 背包

该题是一道背包题,并且是一个0,1背包,这种背包特点是:每种物品仅有一件,可以选择放或不放。

用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:

f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}

这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:将前i件物品放入容量为v的背包中这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为i-1件物品放入容量为v的背包中,价值为f[i-1][v];如果放第i件物品,那么问题就转化为i-1件物品放入剩下的容量为v-c[i]的背包中,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]

#include<stdio.h>
#include
<stdlib.h>
#include
<string.h>
int f[1024][1024];
int v[1024],w[1024];
int main( )
{
int n,m,M;

scanf(
"%d",&M );
for( int i=0; i< M; i++ )
{
memset( f,
0,sizeof( f ) );
scanf(
"%d%d",&n,&m );
for( int j=1; j<=n; j++ )
scanf(
"%d",&w[j] );
for( int j=1; j<=n ;j++ )
scanf(
"%d",&v[j] );
for( int j=1; j<=n; j++ )
for( int k=0; k<=m; k++ )
{
if( k>=v[j]&&f[ j-1 ][ k-v[j] ]+w[j]>f[j-1][k] )
f[j][k]
=f[j-1][ k-v[j] ]+w[j];
else f[j][k]=f[j-1][k];
}
printf(
"%d\n",f[n][m] );
}
return 0;
}

  该题的第二种解法就是对背包的优化解法,当然只能对空间就行优化,时间是不能优化的,先考虑上面讲的基本思路如何实现,肯定是有一个主循环i=1..N,每次算出来二维数组f[i][0..V]的所有值。那么,如果只用一个数组f[0..V],能不能保证第i次循环结束后f[v]中表示的就是我们定义的状态f[i][v]呢?f[i][v]是由f[i-1][v]f[i-1][v-c[i]]两个子问题递推而来,能否保证在推f[i][v]时(也即在第i次主循环中推f[v]时)能够得到f[i-1][v]f[i-1][v-c[i]]的值呢?事实上,这要求在每次主循环中我们以v=V..0的顺序推f[v],这样才能保证推f[v]f[v-c[i]]保存的是状态f[i-1][v-c[i]]的值。伪代码如下:

for i=1..N

    for v=V..0

        f[v]=max{f[v],f[v-c[i]]+w[i]};

注意:这种解法只能由V--0,不能反过来,如果反过来就会造成物品重复放置!

#include<stdio.h>
#include<stdlib.h>
int  DP(int w[],int v[],int N,int M)
{
    int f[1024]={0};
   for( int i=1; i<=N; i++ )
   {
        for( int j=M; j>=0; j-- )
        {
             if( j>=v[i]&&f[ j ]<f[j-v[i]]+w[i] )
                 f[ j ]= f[ j-v[i] ] + w[i];    
        }  
   }
   return f[M];      
}
int  main()
{
    int n,N,M;
    int v[1005],w[1005];
    scanf( "%d",&n );
    for( int i=0; i<n; i++  )
    {
        scanf( "%d%d",&N,&M );
        for( int j=1; j<=N; j++ )
          scanf( "%d",&w[j] );
        for( int j=1; j<=N; j++ )
          scanf( "%d",&v[j] );
         printf( "%d\n",DP( w , v, N ,M ) );     
    }
    return 0;     
}

  

posted @ 2011-08-05 08:50  wutaoKeen  阅读(331)  评论(0编辑  收藏  举报