#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

posted on 2017-03-31 23:47  chenguang9239  阅读(180)  评论(0编辑  收藏  举报