Day43:代码随想录训练营第43天| 1049.最后一块石头的重量II

文章讲述了使用动态规划方法解决LeetCode题目1049,即求背包问题中,给定一系列石头重量,找到使剩余石头重量最轻的背包容量。通过初始化dp数组、确定递推公式和遍历顺序,最后返回满足条件的最大重量。
摘要由CSDN通过智能技术生成

1049.最后一块石头的重量II

题目链接:1049. 最后一块石头的重量 II - 力扣(LeetCode)

题解:本题使用动态规划法,动态规划五部曲

1.确定dp数组以及下标含义

dp[j]表示容量(其实就是重量)为j的背包,最多可以背最大重量为dp[j]

2.确定递推公式

dp[j]=max(dp[j],dp[j - stones[i]] + stones[i])

3.dp数初始化

既然 dp[j]中的j表示容量,那么最大容量(重量)是多少呢,就是所有石头的重量和。

因为提示中给出1 <= stones.length <= 30,1 <= stones[i] <= 1000,所以最大重量就是30 * 1000 。

而我们要求的target其实只是最大重量的一半,所以dp数组开到15000大小就可以了。

当然也可以把石头遍历一遍,计算出石头总重量 然后除2,得到dp数组的大小。

我这里就直接用15000了。

接下来就是如何初始化dp[j]呢,因为重量都不会是负数,所以dp[j]都初始化为0就可以了,这样在递归公式dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);中dp[j]才不会初始值所覆盖。

4.确定遍历顺序

如果使用一维数组,物体遍历for循环在外层,遍历背包for循环在内层

for(int i = 0; i < stones.size(); i++) {
    for (int j = target; j >= stones[i]; j--) {
        dp[j] = max(dp[j], dp[j -  stones[i]] + stones[i]);
     } 
 }

5.举例dp数组

打印dp数组

C代码如下:

#define MAX(a, b) (((a) > (b)) ? (a) : (b))

int getSum(int *stones, int stoneSize) {
    int sum = 0, i;
    for (i = 0; i < stoneSize; ++i)
        sum += stones[i];
    return sum;
}

int lastStoneWeightII(int* stones, int stonesSize){
    int sum = getSum(stones, stonesSize);
    int target = sum / 2;
    int i, j;

    // 初始化dp数组
    int *dp = (int*)malloc(sizeof(int) * (target + 1));
    memset(dp, 0, sizeof(int) * (target + 1));
    for (j = stones[0]; j <= target; ++j)
        dp[j] = stones[0];
    
    // 递推公式:dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])
    for (i = 1; i < stonesSize; ++i) {
        for (j = target; j >= stones[i]; --j)
            dp[j] = MAX(dp[j], dp[j - stones[i]] + stones[i]);
    }
    return sum - dp[target] - dp[target];
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值