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

    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    /******************************** 01背包 */
    #define N 5
    #define M 12
    int value[N + 1] = { 0, 6, 3, 5, 4, 6 };
    int weight[N + 1] = { 0, 2, 2, 6, 5, 4 };
    
    //#define N 5
    //#define M 8
    //int value[N + 1] = { 0, 1, 2, 3, 10, 1 };
    //int weight[N + 1] = { 0, 1, 2, 3, 7, 1 };
    
    int dp[N + 1][M + 1] = { 0 }; //dp[i][j],前i个物品,容量为j的背包,达到的最大价值
    
    int dp1[M + 1] = { 0 }; //将二维空间压缩到一维dp[j],对i迭代,前i个物品,容量为j的背包,达到的最大价值
    int path[N + 1][M + 1] = { 0 }; //打印最佳方案的内容使用,path[i][j]表示
                                    //前i个物品,容量为j的背包,达到最佳方案时,第i个物品是否加入了背包。0/1
    
    
    int main()
    {
    
    for( int i = 0; i <= N; i++ )
    {
        dp[i][0] = 0;
    }
    for( int j = 0; j <= M; j++ )
    {
        dp[0][j] = 0;
    }
    
        //dp[i][j],前i个物品,容量为j的背包,达到的最大价值
        for( int i = 1; i <= N; i++ )
        {
            for( int j = 1; j <= M; j++ )
            {
                if( weight[i] > j )
                {
                    dp[i][j] = dp[i-1][j];
                    continue;
                }
                dp[i][j] = max( dp[i-1][j], dp[i-1][ j-weight[i] ] + value[i] );
            }
        }
        /******************************** 01背包 输出选择 */
        cout << dp[N][M] << endl;
        cout << "We selected: ";
        int i = N, j = M;
        while( i > 0 && j > 0 )
        {
            if( dp[i][j] > dp[i-1][j] ) //说明选择了第i个物品
            {
                cout << i << " ";
                j -= weight[i];//更改背包的容量j
            }
            i--;
        }
    
    
    
    
    
    
    
    for( int j = 0; j <= M; j++ )
    {
        dp1[j] = 0;
    }
        //将二维空间压缩到一维dp[j],对i迭代,第i个物品,容量为j的背包,达到的最大价值
        //在第i轮(考虑第i个物品是否入到容量为j的背包里)的最大价值,会用到第i-1轮
        //(考虑第i-1个物品是否放到容量小于或等于j的背包里)的最大价值。
        //因此j的循环要从大到小,这样才保证在第i轮计算dp[j]使用的是第i-1轮的dp[J](J<=j)。
    
        ///在对i的一次迭代中,如当i=1时,把前i个物品放入容量为j的背包里的最大价值,不依赖于把前i个物品放入容量
        ///小于j的背包里的最大价值,即相同的i时,第i轮dp[j]的计算不依赖第i轮的dp[J],(J<j)。
        for( int i = 1; i <= N; i++ )
        {
            for( int j = M; j >= 1; j-- )
            {
                if( weight[i] > j )
                {
                    //dp1[j] = i-1轮的dp1[j],即不变;这个if判断保证了下面的j-weight[i]不会越界。
                    continue;
                }
                if( dp1[j] < dp1[ j-weight[i] ] + value[i] )
                {
                    path[i][j] = 1;//物品i加入了背包
                }
                dp1[j] = max( dp1[j], dp1[ j-weight[i] ] + value[i] );
            }
        }
        /******************************** 01背包 输出选择 */
        cout << endl << dp1[M] << endl;
        cout << "We selected: ";
        i = N; j = M;
        while( i > 0 && j > 0 )
        {
            if( path[i][j] == 1 ) //说明选择了第i个物品
            {
                cout << i << " ";
                j -= weight[i];//更改背包的容量j
            }
            i--;
        }
    
        return 0;
    }

    两维背包:

    问题描述:1. n个0,m个1

         2. 若干种物品,分别由0和1组成,这些物品是:1, 00, 100

           3. 最多组成多少种物品。

         -------------两维背包,第一维是0的容量为n,第二维是1的容量为m,dp[i][k][j]表示在第一个背包容量为k,第二个背包容量为j的时候,取前i个物品达到的最高价值。这里的价值就是物品的个数。dp[i][k][j]可以压缩到两维dp[k][j]。

    #include <iostream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    vector< string > item; //没有用到
    
    int weight0[21] = { 0 };
    int weight1[21] = { 0 };
    int dp[501][501] = { 0 };
    
    int main()
    {
        int n, m, x;
        cin >> x >> n >> m;
        item.push_back("");
        string s;
        for( int i = 0; i < x; i++ )
        {
            cin >> s;
            item.push_back( s );
    
            int cnt = 0;
            for( int ind = 0; ind < s.length(); ind++ )
            {
                if( s[ind] == '0' )
                {
                    cnt++;
                }
            }
            weight0[i+1] = cnt;
            weight1[i+1] = s.length() - cnt;
            //cout << "i: " << i+1 << " " << weight0[i+1] << " " <<weight1[i+1] << endl;
        }
    
        for( int i = 1; i <= x; i++ )
        {
            for( int k = n; k > 0; k-- )
            {
                for( int j = m; j > 0; j-- )
                {
                    if( weight0[i] > k || weight1[i] > j )
                    {
                        continue;
                    }
                    dp[k][j] = max( dp[k][j], dp[ k-weight0[i] ][ j-weight1[i] ] + 1 );
                }
            }
        }
    
        cout << dp[n][m] << endl;
        return 0;
    }

    参考链接:http://blog.csdn.net/wumuzi520/article/details/7014559

           http://love-oriented.com/pack/P01.html

  • 相关阅读:
    Objective-C之NSArray(数组)默认排序与自定义排序
    Objective-C学习笔记之for( int )机制
    OC之NSString、NSMutableString学习笔记 常用方法
    换行回车的区别 2018-10-30
    Python头部2行 #!/usr/bin/python 和 #!/usr/bin/env 的区别 以及编码方式的指定 2018-10-23
    旧版Windows 睡眠与休眠 2018-10-18
    手机尺寸像素 PPI 2018-10-17
    VMvare 虚拟机扩容 2018-10-11
    批量判断网址能否访问 2018-10-04
    字符串的 strip()方法 2018-10-04
  • 原文地址:https://www.cnblogs.com/wangzhiyi/p/6653943.html
Copyright © 2011-2022 走看看