【20221206】【每日一题】01背包的基础


思路:

二维数组

动规五部曲

1、确定dp数组以及下标含义:二维数组dp[i][j]表示从下标为0-i的物品里任意取,放入容量为j的背包,价值总和最大为多少
2、确定递推关系式:从两个方向推dp[i][j],没放物品i以及放了物品i。没放物品i,由dp[i-1][j](当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以被背包内的价值依然和前面相同),放了物品i,由dp[i-1][j-weight[i]]+value[i],也就模拟了物品i放入后得到的价值。因此递推关系式为:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
3、初始化:背包容量为0时,一定为0;由递推关系可知i状态的价值由i-1状态推导而来,所以物品0的状态都需要初始化,即dp[0][j]。
4、确定遍历顺序:有两种遍历维度,物品与背包重量,先遍历物品更好理解。
5、举例推导dp数组。

void test() {
    vector<int> weight = { 1,3,4,1 };
    vector<int> value = { 15,20,40,25};
    int bagweight = 4;
    //初始化
    vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));
    for (int i = weight[0]; i <= bagweight; i++) 
    {
        dp[0][i] = value[0];
    }
    //两个维度的遍历,先遍历物品,再遍历背包
    for (int i = 1; i < weight.size(); i++)
    {
        for (int j = 1; j <= bagweight; j++)
        {
            if (j < weight[i]) dp[i][j] = dp[i - 1][j];//物品i没放进来
            else  dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
        }
    }
    cout << dp[weight.size() - 1][bagweight] << endl;
}
int main()
{
    test();
}

滚动数组

如果将dp[i-1]那层的数据都拷贝到dp[i]那一层,递推公式其实可以变为:dp[i][j]=max(dp[i][j],dp[i][j-weight[i]]+value[i])。
只用一个一维数组来实现,即滚动数组。能用滚动数组的条件是:上一层可以重复利用,直接拷贝到当前层。

动规五部曲
1、dp数组的意义:dp[j]表示容量为j的背包最大价值为dp[j]
2、递推关系式:dp[j]可以通过dp[j-weight[i]]推导,dp[j]=max(dp[j],dp[j]-weight[i]+value[i])
3、初始化:如果价值都大于0的话,刚开始的时候都初始化为0即可。
4、确定遍历顺序:先物品再背包,注意这里遍历背包的时候是从大到小倒序的目的是为了保证物品i只被放入了一次,从后往前循环,每次取得状态不会和之前取得状态重合,这样每种物品就只取一次了。 注意终止条件:for(int j = bagWeight; j >= weight[i]; j--)
5、举例推导dp数组。

void test01() {
    vector<int> weight = { 1,3,4,1 };
    vector<int> value = { 15,20,40,25 };
    int bagweight = 4;
    
    //初始化
    vector<int> dp(bagweight + 1, 0);
    for (int i = 0; i < weight.size(); i++)
    {
        for (int j = bagweight; j >= weight[i]; j--)//背包倒序
        {
            dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
        }
        for_each(dp.begin(), dp.end(), [=](int x) {cout << x << " "; });
        cout << endl;
    }
    //cout << dp[bagweight] << endl;

}
int main()
{
    test01();
}

将每一次都打印出来,其实发现和二维数组是一样的,节省了空间复杂度。 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值