zoukankan      html  css  js  c++  java
  • 0-1背包简述

    1.0-1背包的朴素形式

    0-1背包问题:给定编号为1,2...n的n个物品和一个容量为C的背包;每个物品的重量为$w_i$,每个物品的价值为$v_i$,求将物品装入背包后,背包能获得的最大价值。其状态转移方程为:

    $$ dp[i][j] = egin{cases} max{dp[i-1][j],dp[i-1][j-w_i] + v_i} ,& {j ≥ w_i} \ dp[i-1][j] , & {j < w_i} end{cases} $$

    其中dp[i][j]表示把编号为从1到i的i个物品放入容量为j的背包所得到的最大的价值。其实现代码如下:

    #include<iostream>
    #include<unordered_map>
    #include<queue>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<sstream>
    #include<set>
    #include<map>
    #include<stack>
    #define MAX_NUM 100
    using namespace std;
    /*0-1背包的朴素形式*/
    
    int main()
    {
        int n,C;//n为物品的个数,C为背包的容量
        int weight[MAX_NUM];
        int val[MAX_NUM];
        int dp[MAX_NUM][MAX_NUM];
        cout<<"输入物品个数和背包容量:"<<endl;
        cin>>n>>C;
        cout<<"分别输入这"<<n<<"个物品的重量和价值:"<<endl;
        for(int i = 1; i <= n; i++)
            cin>>weight[i]>>val[i];
        memset(dp,0,sizeof(dp));//初始化dp数组
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= C; j++) //此处j的初值也可以为weight[i]开始,其实这样效率更高;不过为了便于理解才写成从1开始
            {
                if(j < weight[i])
                    dp[i][j] = dp[i- 1][j];
                else
                    dp[i][j] = max(dp[i - 1][j],dp[i-1][j - weight[i]] + val[i]);
            }
        cout<<"背包的最大价值为:"<<dp[n][C]<<endl;
    }
    

    这种朴素形式的0-1背包的算法的时间复杂度为O(n*C),空间复杂度也为O(n*C)。

     2.对0-1背包进行优化

    对0-1背包的优化主要体现在空间复杂度的优化上,时间复杂度无法再优化了。可以参考:https://blog.csdn.net/hearthougan/article/details/53869671 或者 https://blog.csdn.net/yoer77/article/details/70943462 

    或者 https://www.cnblogs.com/fengziwei/p/7750849.html 。

    其实现代码如下:

    #include<iostream>
    #include<unordered_map>
    #include<queue>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<sstream>
    #include<set>
    #include<map>
    #include<stack>
    #define MAX_NUM 100
    using namespace std;
    /*0-1背包的优化形式*/
    
    int main()
    {
        int n,C;//n为物品的个数,C为背包的容量
        int weight[MAX_NUM];
        int val[MAX_NUM];
        int dp[MAX_NUM];//变成了一位数组
        cout<<"输入物品个数和背包容量:"<<endl;
        cin>>n>>C;
        cout<<"分别输入这"<<n<<"个物品的重量和价值:"<<endl;
        for(int i = 1; i <= n; i++)
            cin>>weight[i]>>val[i];
        memset(dp,0,sizeof(dp));//初始化dp数组
        for(int i = 1; i <= n; i++)
            for(int j = C; j >= 1; j--) //此处j的初值变成了C,然后递减;与朴素形式调过来了;当然此处的中止条件也可为j >= weight[i]
            {
                if(j < weight[i])
                    dp[j] = dp[j];
                else
                    dp[j] = max(dp[j],dp[j - weight[i]] + val[i]);
            }
        cout<<"背包的最大价值为:"<<dp[C]<<endl;
    }
    

    优化后的0-1背包算法,时间复杂度仍为O(n*C),空间复杂度变成了O(C)。

  • 相关阅读:
    Docker02 Docker初识:第一个Docker容器和Docker镜像
    Docker01 CentOS配置Docker
    Jenkins02:Jenkins+maven+svn集成
    Junit01 新建Maven项目
    Junit02 Junit创建及简单实现
    Jenkins01:linux+jenkins+ant+jmeter集成
    Jenkins初识03:构建定时任务
    python 协程
    python之socket 网络编程
    python 面向对象
  • 原文地址:https://www.cnblogs.com/wangkundentisy/p/9336208.html
Copyright © 2011-2022 走看看