【杭电ACM】2602

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;
}

      我的想法已经写完了,有不足之处请大神们批评,不过  如果文字真的很难懂的话不妨按我图片上的数组变化形式走一遍。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值