4 0-1背包(加强版,并输出物体编号)

本文介绍了一种解决背包问题的经典动态规划方法,并通过具体示例演示了如何求解最大价值及选择哪些物品来达到这一价值。代码实现部分详细展示了状态转移方程的设计思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个旅行者有一个最多能装 M 公斤的背包,现在有 n 件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn,求旅行者能获得最大总价值。

输入格式:

第一行:两个整数,M(背包容量,M<=200)和N(物品数量,N<=30);

第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。

输出格式:

第一行,一个数,表示最大总价值。

第二行,按从小到大输出物品编号,编号间用一个空格隔开,最后一个数后有一个空格。

输入样例:

10 4
2 1
3 3
4 5
7 9

输出样例:

12
2 4 

样例说明:表示选第2,4两件物品得到最大价值12

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;

int t[110]; //各个商品的体积
int v[110]; //各个商品的价值

int dp[110][1010] = {0};//代表取第i种商品,在体积为j时的最大价值***
int dp2[110][1010] = {0}; //用于寻找购买的商品,初始化都为0
int resort[110] = {0}; //用于存放结果,按要求正序或逆序输出

int T; //背包总容量
int M; //商品个数
void show(); //测试用


void KnapSackDP(int n, int T); //输出选择的商品编号

int main()
{
    //输入背包容量T和商品总数M
    cin >> T >> M;
    for(int i = 1; i <= M; i++)
    {
        //输入每个商品的体积t和价值v
        cin >> t[i] >> v[i];
    }


    for(int i = 1; i <= M; i++)
    {
        for(int j = T; j >= 0; j--) //从后往前是为了滚动数组做准备
        {
            if(t[i] > j)
            {
                dp[i][j] = dp[i-1][j];

            }

            else
            {
                dp[i][j] = max(dp[i-1][j],dp[i-1][j-t[i]]+v[i]);
                if(dp[i][j] == dp[i-1][j-t[i]]+v[i])
                {
                    dp2[i][j] = 1;//当他是1,就说明当前体积下,最优解里有这个商品
                }
                if(dp[i][j] == dp[i-1][j])
                    dp2[i][j] = 0;//当它是0,就说明当前体积下,最优解里没有这个商品

            }

        }
    }

    cout << dp[M][T] << endl;
    KnapSackDP(M, T);
    //show();
    return 0;

}

void show()
{
    for(int i = 1; i <= 5; i++)
    {
        for(int j = 0; j <= 13; j++)
            cout << dp2[i][j] << ' ';
        cout << endl;
    }

}

//输出最优解的选择,
//商品总数n,各商品价值v,各商品体积p,总容量T
void KnapSackDP(int n, int T)
{
    //从最后那个开始,减去其体积后,看上一层是1,还是0
    int i = n, j = T, k = 0;
    while(i)
    {   
        //是1输出该商品,然后减去该商品的体积再看上一层
        if(dp2[i][j] == 1)
        {
           // cout << i << ' ';
            resort[k++] = i;
            j -= t[i];
        }
        i--;
    }//是0就不输出,直接看上一层
    for(int m = k-1; m >=0; m--)
    {
        cout << resort[m] << ' ';
    }
    
    
}


/*测试用例
70 3
71 100
69 1
1 2
答案:3

13 5
10 24
3 2
4 9
5 10
4 9
答案:28
13 5
3 2
4 9
5 10
4 9
10 24
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百年bd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值