01背包
在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2……Wn,与之相对应的价值为P1,P2……Pn。与之相似的问题。下面以杭电2602题为例分析。
Many years ago , in Teddy’s hometown there was a man who was called “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 his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ?
Input
The first line contain a integer T , the number of cases.
Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.
Output
One integer per line representing the maximum of the total value (this number will be less than 231).
Sample Input
1 5 10 1 2 3 4 5 5 4 3 2 1
Sample Output
14
大概的题意就是泰迪喜欢收集骨头,他背了一个容量为V的包去了坟地,收集骨头,但是不一样的骨头体积不同价值也不同,求出在不超出包的容量是泰迪能获得的最大利益。
这就是典型的01背包问题。一种物品只有一个“题目中INPUT 中给的N的值为the number of而非天the kind of...”这就说明这道题是01背包,而非完全背包。
对于01背包分析问题时有固定的思路:大体上是将限制条件(这里为N)作为包的容量,将想求的东西(这里为骨头价值)作为数组中元素的值。将所给物品依次进行“输入”,在数组中从后向前不断更新数组的值,当最后一件物品比较完之后,数组中最后一个元素的值就为所求的解(这里为包中能装下骨头的最大价值)。【当然也有特例,像杭电的2995中就不能用这种思路,但大体上方法是一致的。】
下面为更新的情况,当然,我们所申请的为一维数组,写成这种格式是为了更能看清:当输入一个物品时数组的变化情况。(ps:数组在申请内存之后就被赋予了初值0)
从图片中我们也可以看出,按题意我们进行分析后,数组中最后一个值14也正是我们所求解。
下面附上简陋代码:
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1005;
int value[N],volume[N],v,f[N];
int zop(int volue,int volume)
{
for(int i=v;i>=0;i--) //从后向前写数组;
{
if(i>=volume) f[i]=max(f[i],f[i-volume]+volue); //根据比较求出最优解。
}
}
int main()
{
int t,n,i;
while(~scanf("%d",&t))
{
while(t--)
{
memset(f,0,sizeof(f)); //快速赋初值,若用循环将数组初值均置0,耗内存也是耗时间的。
scanf("%d%d",&n,&v); //以下为题意输入;
for(i=0;i<n;i++)
scanf("%d",&value[i]);
for(i=0;i<n;i++)
scanf("%d",&volume[i]);
for(i=0;i<n;i++) //将n件物品依次送入zop函数;
zop(value[i],volume[i]);
printf("%d\n",f[v]); //f数组已为全局变量,经过上面的循环后,输出数组最后一个元素值。
}
}
return 0;
}
我的想法已经写完了,有不足之处请大神们批评,不过 如果文字真的很难懂的话不妨按我图片上的数组变化形式走一遍。