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

      

  • 相关阅读:
    简单工厂模式_C#_设计模式
    单例模式_C#设计模式
    快速排序_排序算法_算法
    关于缓存C#
    网络编程的4种IO模型
    一些自己总结
    驱动漏洞中的__try和ProbeForRead
    poj2318
    poj1113
    poj 1904
  • 原文地址:https://www.cnblogs.com/l1l1/p/9486680.html
Copyright © 2011-2022 走看看