zoukankan      html  css  js  c++  java
  • 完全背包详解_动态规划

    题目描述

    设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于M ,而价值的和为最大。

    输入

    第一行:两个整数,M(背包容量,M<=200)和N(物品数量,N<=30);第2..N+1 行:每行二个整数Wi,Ui,表示每个物品的重量和价值。

    输出

    仅一行,一个数,表示最大总价值,格式如样例。

    样例输入

    10 4 
     2  1 
     3  3 
    4  5 
    7  9 
    

    样例输出

    max=12
    

    解析

    (dp(i,j))表示前(i)个物品装入(j)重量背包中能够得到的最大总价值。

    状态方程1:

    (dp(i,j)=max{dp(i-1,j-k imes w[i])+k imes v[i]mid 0leq k})

    (dp(0,j)=0quad dp(i,0)=0)

    程序片段:

    const int MaxN=100,MaxW=10000;
    int dp[MaxN+1][Maxw+1];
    int n,w[MaxN+1],v[MaxN+1],W;
    
    /*输入*/
    cin>>W>>n;
    for(int i=1;i<=n;i++)
        cin>>w[i]>>v[i];
    memset(dp,0,sizeof(dp));
    
    /*动态规划计算*/
    for(int i=1;i<=n;i++)
        for(int j=1;j<=W;j++)
            for(int k=0;k*w[i]<=k;k++)
                dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]}+k*v[i]);
    
    cout<<"max="<<dp[n][W]<<endl;
    

    空间复杂度:O(n*W);
    时间复杂度:O(n*W*W);

    状态方程2:

    [dp(i,j)=max{dp(i-1,j-k imes w[i])+k imes v[i]mid 0leq k} ]

    [egin{aligned} dp(i,j)=max{&dp(i-1,j),\ &oxed{dp(i-1,j-w[i])}+v[i],\ &oxed{dp(i-1,j-2cdot w[i])+v[i]}+v[i], dots } end{aligned} ]

    对比

    [egin{aligned} dp(i-1,j-w[i])=max{&oxed{dp(i-1,j-w[i])},\ &oxed{dp(i-1,j-2cdot w[i])+v[i]},\ &dp(i-1,j-3cdot w[i])+2cdot v[i], dots} end{aligned} ]

    得到

    [dp(i,j)=max{dp(i-1,j),dp(i-1,j-w[i])+v[i]} ]

    程序片段(改进时间):

    /*动态规划计算*/
    for(int i=1;i<=n;i++)
        for(int j=1;j<W;j++)
            if(j<W[i]) dp[i][j]=dp[i-1][j];
            else dp[i][j]=max(dp[i-1][j],dp[i][j-w[i]]+v[i]);
    

    空间复杂度:O(n*W)
    时间复杂度:O(n*W)

    程序片段(压成一维):

    int dp[MaxN+1];
    
    /*动态规划计算*/
    for(int i=1;i<=n;i++)
        for(int j=1;j<W;j++)
            if(j>W[i]) dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    

    空间复杂度:O(W)
    时间复杂度:O(n*W)

    类似问题:牛奶容器

    题目描述

    农民保罗有如下型号的牛奶容器: 10加伦,2加伦,1 加伦,1/4加伦,1/8加伦, 1/16加伦。

    请您帮他编写一个程序,能计算保罗用这些容器取X加伦牛奶共有多少不同方法。在所有的数据中,X都是整数且(1<=X<=100)。

    输入

    输入数据中有多组测试数据,每组测试数组仅有一行,包含一个整数x。最后一行以0表示结束。
    输出

    对于每组数据,输出一行,为保罗用这些容器取x加伦牛奶共有的不同方法数。

    样例输入

    5
    10
    0
    

    样例输出

    1308
    12477
    
  • 相关阅读:
    教程:在 Visual Studio 中开始使用 Flask Web 框架
    教程:Visual Studio 中的 Django Web 框架入门
    vs2017下发现解决python运行出现‘No module named "XXX""的解决办法
    《sqlite权威指南》读书笔记 (一)
    SQL Server手工插入标识列
    hdu 3729 I'm Telling the Truth 二分图匹配
    HDU 3065 AC自动机 裸题
    hdu 3720 Arranging Your Team 枚举
    virtualbox 虚拟3台虚拟机搭建hadoop集群
    sqlserver 数据行统计,秒查语句
  • 原文地址:https://www.cnblogs.com/1024th/p/10421436.html
Copyright © 2011-2022 走看看