• 动态规划---01背包问题(1)


    模型框架:有一个空间为V的容器,需要从n个物品(包含属性:所占空间volume,价值value)中挑选几件物品使得容器中的价值最大。

    问题解决思路:

    比如有一个口袋,容量是4,有3个物品,分别是编号1:吉他(空间占用:1;价值:1500)、编号2:音响(空间占用:4;价值:3000)、编号3:笔记本电脑(空间占用:3;价值:2000),问如何挑选使得口袋能得到最大价值。

    有人会说,那我一个一个尝试过去就能知道了,只是时间花的久一点(这里时间久的可不是一点点←_←)

    举个例子来说:我现在这个例子有3个物品,排列组合一下就有(空)(1)(2)(3)(1,2)(1,3)(2,3)(1,2,3)8种情况,要是4个就有24=16,5个就有25=32种,这种算法运行时间为O(2n),简直不要太慢了好嘛(゚ー゚)

    所以这就要提到今天需要新学的算法动态规划中的01背包问题

    动态规划一般是把大问题拆分为小问题,用表格的方式来解决问题

    假设现在我们只有编号1的吉他可以选, 

    物品容量 1 2 3 4
    吉他(1/1500) 1500(吉他) 1500(吉他) 1500(吉他) 1500(吉他)

    现在我们再加上编号2的音响

    物品容量 1 2 3 4
    吉他(1/1500) 1500(吉他) 1500(吉他) 1500(吉他) 1500(吉他)
    音响(4/3000) 1500(吉他) 1500(吉他) 1500(吉他) 3000(音响)

    我们再加上编号3的笔记本电脑

    物品容量 1 2 3 4
    吉他(1/1500) 1500(吉他) 1500(吉他) 1500(吉他) 1500(吉他)
    音响(4/3000) 1500(吉他) 1500(吉他) 1500(吉他) 3000(音响)
    笔记本电脑(3/2000) 1500(吉他) 1500(吉他) 2000(笔记本电脑) 3500(笔记本电脑+吉他)

    通过这个过程,可以观察到其中包含了一个公式

    dp[i][j]=max(dp[i-1][j],dp[i-1][j-当前物品占用空间]+当前物品的价值)
    前半部分指的是当前这个物品的容量要大于我现在有的容量(也就是装不下这个物品了,这个时候我们需要用没有这个物品的情况下,能获取的最大价值),或者是放弃(不考虑)当前这个物品
    后半部分说的是:能装下当前这个物品,但是还有多余的空间,那就去对应的那个空间看看,这个剩余的空间能装下最多是多少的价值
    最后取其中最大的,也就是我们需要求的答案了

    既然算法了解了,来几道题测一测(゚ー゚)

    例题1:

    原题链接

    Bone Collector

    Problem Description

    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,需要收集的骨头分别有容量weight和价值value,给你一些骨头的容量和价值,需要你求出这个袋子可以装下骨头的最大价值。
     
    方法一:
     1 //二维数组
     2 #include <stdio.h>
     3 #include <string.h>
     4 
     5 int T,n,v;
     6 int value[1005];//价值
     7 int volume[1005];//容量
     8 int s[1005][1005];//存最大价值的数组
     9 int maxx(int a,int b);
    10 int main(void)
    11 {
    12     int i,j,k;
    13     scanf("%d",&T);
    14     while(T--)
    15     {
    16         memset(value,0,sizeof(value));
    17         memset(volume,0,sizeof(volume));
    18         memset(s,0,sizeof(s));//这个必须要清空
    19         scanf("%d%d",&n,&v);
    20         for(i=1;i<=n;i++)
    21             scanf("%d",&value[i]);
    22         for(i=1;i<=n;i++)
    23             scanf("%d",&volume[i]);
    24         for(i=1;i<=n;i++)
    25         {
    26             for(j=0;j<=v;j++)
    27             {
    28                 if(volume[i]<=j)//装的下
    29                 {
    30                     s[i][j]=maxx(s[i-1][j],value[i]+s[i-1][j-volume[i]]);
    31                     //比较没有装当前这个物品的价值 和 装了当前这个物品的价值+剩余空间的最大价值
    32                 }
    33                 else//装不下
    34                 {
    35                     s[i][j]=s[i-1][j];
    36                 }
    37             }
    38         }
    39         printf("%d
    ",s[n][v]);//最后一个位置就是最大价值
    40 
    41     }
    42     return 0;
    43 }
    44 
    45 int maxx(int a,int b)
    46 {
    47     return a>b?a:b;
    48 }

    方法二:

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 int maxx(int a,int b);
     5 
     6 int dp[1005];//存放最大价值的数组
     7 int value[1005];//价值
     8 int volume[1005];//容量
     9 
    10 int main(void)
    11 {
    12     int T,n,v;
    13     int i,j,k;
    14     scanf("%d",&T);
    15     while(T--)
    16     {
    17         memset(dp,0,sizeof(dp));//必需清空
    18         scanf("%d%d",&n,&v);
    19         
    20         for(i=1;i<=n;i++)
    21             scanf("%d",&value[i]);
    22         for(i=1;i<=n;i++)
    23             scanf("%d",&volume[i]);
    24         
    25         for(i=1;i<=n;i++)
    26         {
    27             for(j=v;j>=volume[i];j--)//注意这个要从后往前倒序,如果不这样就会不止取到一个当前这个物品
                            (比如:物品容量是1,从前往后排,容量为2的时候取到了自己再去取容量为1的自己,
                            但是物品只有一个,所以为了避免这个问题,就从后往前取了)
    28 { 29 dp[j]=maxx(dp[j],dp[j-volume[i]]+value[i]); 30 } 31 } 32 printf("%d ",dp[v]); 33 } 34 35 return 0; 36 } 37 38 int maxx(int a,int b) 39 { 40 return a>b?a:b; 41 }
     
     
  • 相关阅读:
    webpack实践(三)- html-webpack-plugin
    webpack实践(二)- webpack配置文件
    webpack实践(一)- 先入个门
    VueRouter爬坑第三篇-嵌套路由
    VueRouter爬坑第二篇-动态路由
    chrome中安装Vue调试工具vue-devtools
    VueRouter爬坑第一篇-简单实践
    使用vue-cli搭建项目开发环境
    Jmeter基础001----jmeter的安装与配置
    接口测试基础001----接口、接口测试
  • 原文地址:https://www.cnblogs.com/NIT-yale/p/13263388.html
Copyright © 2020-2023  润新知