01背包问题     杭电 2602

来源:互联网 发布:淘宝客商品采集技巧 编辑:程序博客网 时间:2024/05/06 12:18
原文地址:    杭电 2602">01背包问题     杭电 2602作者:泪枫聆

动态规划是用空间换时间的一种方法的抽象。其关键是发现子问题和记录其结果。然后利用这些结果减轻运算量。
比如01背包问题。比如杭电 2602     http://acm.hdu.edu.cn/showproblem.php?pid=2602

Problem Description
Many years ago , in Teddy’s hometown there was a man who wascalled “Bone Collector”. This man like to collect varies of bones ,such as dog’s , cow’s , also he went to the grave …
The bone collector had a big bag with a volume of V ,and along histrip of collecting there are a lot of bones , obviously , differentbone has different value and different volume, now given the eachbone’s value along his trip , can you calculate out the maximum ofthe total value the bone collector can get ?
[转载]01背包问题 <wbr> <wbr> <wbr> <wbr> <wbr>杭电 <wbr>2602

 


 

Input
The first line contain a integer T , the number ofcases.
Followed by T cases , each case three lines , the first linecontain two integer N , V, (N <= 1000 , V<= 1000 )representing the number of bones and thevolume of his bag. And the second line contain N integersrepresenting the value of each bone. The third line contain Nintegers representing the volume of each bone.
 


 

Output
One integer per line representing the maximum of the totalvalue (this number will be less than 231).
 


 

Sample Input
1 5 10 1 23 4 5 5 4 3 2 1
 


 

Sample Output
14
 
 

因为背包最大容量M未知。所以,我们的程序要从1到M一个一个的试。比如,开始任选N件物品的一个。看对应M的背包,能不能放进去,如果能放进去,并且还有多的空间,则,多出来的空间里能放N-1物品中的最大价值。怎么能保证总选择是最大价值呢?看下表

 

 

[转载]01背包问题 <wbr> <wbr> <wbr> <wbr> <wbr>杭电 <wbr>2602

P[i][j]数组保存了1,2,3,4,5号物品依次选择后的最大价值.

这个最大价值是怎么得来的呢?

从背包容量,为0开始,1号物品先试0,1,2,3,4的容量都不能放.所以置0,背包容量为5则里面放价值为1.这样,这一排背包容量为6,7,8....10的时候,最佳方案都是放价值1.则再看2号物品.当背包容量为4的时候,里面放入价值为2,背包容量为9的时候,放入2号物品的时候还有空余空间,很显然是2加上一个值了。加谁??很显然是9-4=5的时候.上一排P5的最佳方案是1.所以,总的最佳方案是为3.再比如放4号物品的时候,当背包容量为2,放入价值为4的物品,当背包容量为5的时候,4加上上一排的p(5-2)的最佳方案为3,等于7.之后的9也是这样的道理。这样.一排一排推下去。最右下放的数据就是最大的价值了。

从以上最大价值的构造过程中可以看出。

 

f(n,m)=max{f(n-1,m),f(n-1,m-w[n])+P(n,m)}这就是书本上写的动态规划方程.这回清楚了吗?

 

下面是实际程序:

#include<iostream>
using namespace
std;
int
p[1000][1000];
int
max(inta,int b)
{

   if
(a>b)
       return
a;
    else
       return
b;
}


int
main()
{

   int
T,N,M,i,j;
   int
a[1000],b[1000];
   cin>>T;
   while
(T--)
   {

       cin>>N>>M;
       for
(i=1;i<=N;i++)
           cin>>a[i];
       for
(i=1;i<=N;i++)
           cin>>b[i];
       memset(p,0,sizeof(p));     
       for
(i=1;i<=N;i++)
           for
(j=0;j<=M;j++)
           {

               if
(b[i]<=j     
                   p[i][j]=max(p[i-1][j],p[i-1][j-b[i]]+a[i]);

                   

                       
               else

                   p[i][j]=p[i-1][j];
           }

       cout<<p[N][M]<<endl;
   }

   return
0;
}

 

其中for(j=0;j<=M;j++)中j=0时瑟吉欧这样解释的,如果你一个麻袋东西,然后有一个戒指,它的体积可以忽略也0;所以要从0开始,下面是这个程序优化的

 

#include<iostream>
usingnamespace std;

int
max(inta,intb)
{

   if
(a>b)
       return
a;
   else
       return
b;
}


int
main()
{

   int
m,n,v,i,j;
   int
a[1000],b[1000],p[1000];
   cin>>m;
   while
(m--)
   {

       cin>>n>>v;
       for
(i=1;i<=n;i++)
           cin>>a[i];
       for
(i=1;i<=n;i++)
           cin>>b[i];
       memset(p,0,sizeof(p));
       for
(i=1;i<=n;i++)
           for
(j=v;j>=b[i];j--)
               p[j]=max(p[j],p[j-b[i]]+a[i]);
       cout<<p[v]<<endl;
   }

   return
0;
}

 

还有谢谢dingqiqi2009 同学做参考。



0 0