Exercise(4):01背包(简单动规)问题的两种解法

/*
    注:本题使用VC++6.0 版本 语言:C++

    有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。
    求解将哪些物品装入背包可使价值总和最大。
    输入:
    第一行两个整数分别是N件物品与背包容量V
    接下来分别是N行,每行两个数分别是当前物品的重量w与价值v;

    输出:
    在不超过背包容量的前提下输出最大的价值总和。

    测试数据:
    5 10
    2 6
    2 3
    6 5
    5 4
    4 6 

    15

*/
// 建议可以用excel表格建表并按照代码一步一步分析

-------------------------二维-------------------------
#include <iostream>
using namespace std;
int max(int,int);

int main()
{
    // n为物品件数 m为背包容量 i,j为循环变量
    int n,m,i,j;                
    cin>>n>>m;

    // w[100]为各物品重量 v[100]为各物品价值
    int w[100],v[100];
    // 此处空出第1行,第1列初始化为0
    for( i = 1; i <= n; ++i )   
        cin>>w[i]>>v[i];

    // d[100][100]为最大价值表 此处初始化第1行,第1列为0
    int d[100][100];
    for( i = 0; i <= n ; ++i )
        d[i][0] = 0;
    for( i = 0; i <= m; ++i )
        d[0][i] = 0;

    // 从d[1][1]开始遍历
    for( i = 1; i <= n; ++i )
        for( j = 1; j <= m; ++j )
            // 当物品重量大于对应背包容量时,价值为0
            if(j < w[i]) d[i][j] = 0;   
            else
            // 状态转移方程:
            /*
                对于当前物品w[i]有两种状态:装和不装
                ①不装:若不装入,则以上一级的值 d[i-1][j] 
                  为d[i][j]的值。
                ②装:若装入,则需要计算装入该物品后背包剩余
                  的容量j-w[i]在上一级的最大价值 
                  d[i-1][j-w[i]] .
                最后比较装与不装 哪种状态价值更大,选择最大。
            */
                d[i][j] = max(d[i-1][j-w[i]]+v[i],d[i-1][j]);

    // 表格完成后,有效数据域内右下角的值为最大价值。
    cout<<d[n][m]<<endl;
    return 0;
}

// 一般来说在标准C++库内已经含有max函数,无需自行定义。
// 但由于编译环境版本低的问题 需要自行定义
int max(int a, int b)
{ return (a>b?a:b); }

// 计算价值表时不一定要从上到下,也可以从下到上。

-------------------------一维-------------------------
// 可参考二维解法思考一下一维解法,改变处已标出
#include <iostream>
using namespace std;
int max(int,int);

int main()
{
    int n,m,i,j;                
    cin>>n>>m;

    int w[100],v[100];
    w[0] = 0; v[0] = 0;  //此
    for( i = 1; i <= n; ++i )   
        cin>>w[i]>>v[i];

    int d[100];  //此
    for( i = 0; i <= m; ++i )  
        d[i] = 0;  //此

    for( i = 1; i <= n; ++i ) //此
        for( j = m; j >= w[i]; --j )  //此
                d[j] = max(d[j-w[i]]+v[i],d[j]);  //此

    cout<<d[m]<<endl;  //此
    return 0;
}

int max(int a, int b)
{ return (a>b?a:b); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值