zoukankan      html  css  js  c++  java
  • 01背包

    处理何种问题:给定n种物品和一个容量为V的背包,物品i的体积为vi,其价值为pi,求其最终可以装进背包的物品最大价值。

     

    性能:时间复杂度为O(nV)

     

    原理

    1. 首先明确一点:对于先放那个物品对最后结果无影响
    2. 设 dp[i][j] 为有前i个物品,且容量为j时背包所能得到的最大价值(暂时不要问是怎么得出dp[i][j]值的),则当出现第(i+1)个物品时,dp[i+1][j]=max(dp[i][j] ,dp[i][j-arr[i+1].v]+arr[i+1].p),即比较在不装这个物品的情况下的背包最大价值和装了这个物品下的最大价值的大小,进行取舍。
    3. 只要将dp[0][j] 都设置为0,其状态转移方程就也适用1~n个物品。

     

    实现步骤:对于该状态转移方程的二维数组实现方式我就不在这里说了。

    一维数组的实现方式:因为该方程式其实每次只需要考虑第i个和第i-1个,可以用2个一维数组去滚动求解,也可以只用一个一维数组进行求解,坑点在于为了保证(j-arr[i].v) 访问的是第i-1个物品的数据,j的遍历顺序必须是(V~arr[i].v)否则会提前修改数据,导致后面的不可用。

     

    备注:dp求解和递归求解在思考模式上还是有很大不同的。

    标准的状态转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-arr[i].v]+arr[i].p);

     

    输入样例解释

    5 1000//5种物品,背包容量为1000

    144 990 //第1种物品的体积、价值

    487 436

    210 673

    567 58

    1056 897

     

    输出样例解释

    2099//最大价值

     

    #include<iostream>
    #include<cstdio>
    #include<string.h>
    using namespace std;
    const int MaxN=100010;
    struct node
    {
        int p,v;
    };
    node arr[MaxN];
    int dp[MaxN];
    int N,V;
    
    int main()
    {
        scanf("%d%d",&N,&V);
        for(int i=1;i<=N;++i)
            scanf("%d%d",&arr[i].v,&arr[i].p);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=N;++i)
        {
            for(int j=V;j>=arr[i].v;--j)
            {
                dp[j]=max(dp[j],dp[j-arr[i].v]+arr[i].p);
            }
        }
        printf("%d
    ",dp[V]);
        return 0;
    }
    

      

  • 相关阅读:
    Android 摇一摇之双甩功能
    Android 上千张图片的列表滑动加载
    Android 新手引导
    Android 自定义列表指示器
    Mininet的安装与卸载
    ubuntu装机必备
    linux系统中利用vagrant创建虚拟开发环境
    Ubuntu右键添加:open in terminal
    ryu启动问题总结
    新建WORD文档打开会出现转换文件对话框3步解决办法
  • 原文地址:https://www.cnblogs.com/l1l1/p/9486680.html
Copyright © 2011-2022 走看看