zoukankan      html  css  js  c++  java
  • 模板【背包问题】

    PART1(算法思想简介)

    1.实现:

    2.时间复杂度:

    3.特别优势:

    4.适用情况:

    5.需要注意的点:

    6:函数、变量名的解释+英文:

    volume(体积)
    quantity(数量)

    PART2(算法各种类型(并附上代码))

     TYPE1 01背包:

    普通解法:O(VN)【空间也是O(VN)】从1~n件物品,对已经用了j的空间的情况下尝试放入(其实可能没有用到这么多的空间,但这样的答案肯定更新不了最优解【大的空间放的东西肯定比小的空间多】,所以没关系啦),放得下的就放进去看能不能更新最优解。

    #include <iostream>
    #include <cstring>
    using namespace std;
    const int N = 21;
    const int V = 1e3+10;
    int bagDp[N][V];
    int value[N], volume[N];
    int main() {
        int n, v;
        cin >> n >> v;
        for(int i = 1;i <= n;i++){
            cin >> value[i] >> volume[i];
        }
        for(int i = 1;i <= n;i++){
            for(int j = 0;j <= v;j++){
                if(j >= volume[i]){//提前判断装不装得下
                    bagDp[i][j] = max(bagDp[i - 1][j - volume[i]] + value[i],bagDp[i - 1][j]);
                }else {//要记得这个处理
                    bagDp[i][j] = bagDp[i - 1][j];
                }
            }
        }
        cout << bagDp[n][v] <<endl;
        return 0;
    }
    View Code

    空间压缩优化:O(VN)【但是空间是O(V)了】i物品存放本来是由i-1层跟新来的,但是如果j从V~1,因为dp[i][j]必然是由dp[i-1][j-v[i]]【也就是空间更小的更新来的】,我们就可以压缩一下,只需要一重dp[1~V]就成

    #include <iostream>
    #include <cstring>
    using namespace std;
    const int N = 21;
    const int V = 1e3+10;
    int bagDp[V];
    int value[N], volume[N];
    int main() {
        int n, v;
        cin >> n >> v;
        for(int i = 1;i <= n;i++){
            cin >> value[i] >> volume[i];
        }
        for(int i = 1;i <= n;i++){
            for(int j = v;j >= volume[i];j--){
                bagDp[j] = max(bagDp[j-volume[i]] + value[i], bagDp[j]);
            }
        }
        cout << bagDp[v] <<endl;
        return 0;
    }
    View Code

     TYPE1 多重背包:

    普通解法:

    #include <iostream>
    #include <cstring>
    using namespace std;
    const int N = 21;
    const int V = 1e3+10;
    int bagDp[N][V];
    int value[N], volume[N], quantity[N];
    int main()
    {
        int n, v;
        cin >> n >> v;
        for(int i = 1; i <= n; i++)
        {
            cin >> value[i] >> volume[i] >> quantity[i];
        }
        for(int i = 1; i <= n; i++)
        {
            for(int j = v; j >= volume[i]; j--)
            {
                for(int k = 0; k <= quantity[i]; k++)
                    if(j >= volume[i]*k)
                        bagDp[i][j] = max(bagDp[i-1][j-volume[i]*k] + value[i]*k, bagDp[i][j]);
                    else
                        break;
            }
        }
        cout << bagDp[n][v] <<endl;
        return 0;
    }
    View Code

    空间压缩版本:只要J是逆序地就不重复覆盖(树上例题)

    #include <iostream>
    #include <cstring>
    using namespace std;
    const int N = 21;
    const int V = 1e3+10;
    int bagDp[V];
    int value[N], volume[N], quantity[N];
    int main()
    {
        int n, v;
        cin >> n >> v;
        for(int i = 1; i <= n; i++)
        {
            cin >> value[i] >> volume[i] >> quantity[i];
        }
        for(int i = 1; i <= n; i++)//总共有t组 从第一组开始
        {
            for(int j = v; j >= volume[i]; j--)//背包容积剩余 j
            {
                for(int k = 0; k <= quantity[i]; k++)//这组里面有多少个元素
                    if(j >= volume[i]*k)
                        bagDp[j] = max(bagDp[j-volume[i]*k] + value[i]*k, bagDp[j]);
                    else
                        break;
            }
        }
        cout << bagDp[v] <<endl;
        return 0;
    }
    View Code

    二进制优化:

    根据把quantity[i]分解成二进制数来把其分成log(quantity[i])件物品

     TYPE1 无穷背包:

     用j来限制使得无穷背包转化为多重背包

     甚至,都不用枚举k了,用dp[i][v-c[i]]更新dp[i][v]就行

     

     空间优化:

    #include <iostream>
    #include <cstring>
    using namespace std;
    const int N = 21;
    const int V = 1e3+10;
    int bagDp[V];
    int value[N], volume[N];
    int main() {
        int n, v;
        cin >> n >> v;
        for(int i = 1;i <= n;i++){
            cin >> value[i] >> volume[i];
        }
        for(int i = 1;i <= n;i++){
            for(int j = volume[i];j <= v;j++){
                bagDp[j] = max(bagDp[j-volume[i]] + value[i], bagDp[j]);
            }
        }
        cout << bagDp[v] <<endl;
        return 0;
    }
    View Code

    PART3(算法的延伸应用)

    PART4(对算法深度的理解)

    PART5(与其相关的有趣题目)

     

  • 相关阅读:
    Python 类 元类 new之间的关系
    Scrapy Item类分析
    python中的可变参数和不可变参数
    简易python购物车
    关于Javascrip瀑布流深度解析
    python3.5 的str类型和bytes类型的转换
    php 扩展
    PHP开源网
    ElementUI中树形控件el-tree修改样式/添加title
    SVN 重命名文件夹
  • 原文地址:https://www.cnblogs.com/bear-xin/p/14968550.html
Copyright © 2011-2022 走看看