Day2-2021.1.10 背包问题的学习+整理。little。

2021年1月10日 时间都去哪了?

今日计划:力扣题目刷到150。javaweb进行下去,或者学习计算机网络。

今日工作:力扣题目刷到147。主要是背包问题还挺难搞???
1.背包问题的学习+整理。
2.416. 分割等和子集
3.解决了Typora笔记上传到CSDN的图片失效问题。
4.逛县城。试做小火锅,经验++。傍晚跑步

今日总结:
在家的效率是打了大大的折扣。
年前补基础,年后找实习。✔

今日语录:
女作家多丽丝·莱辛在《幸存者回忆录》中,写过这样一段话:
“我们浪费自己的健康,去赢得个人的财富,然后又浪费自己的财富,去重建自己的健康。
“我们焦虑地憧憬着未来,忘记了眼前的生活,活得既不是为了现在,也不是为了未来。
“我们活得似乎永远不会死,我们死得好像从来没活过。”

明天计划:整理背包问题的笔记。力扣题目刷到150+。
明天是新的一周了。下周刷题20道。力扣到达170。开始学习项目吧。
可以研读一下:大雪菜的背包九讲+也可以加入大雪菜的寒假刷题班5元

转到2021.1.9-2021.1.31的learning record 首页

[9 5.mp4]

0-1背包问题 视频教程

相关问题
「力扣」上的 0-1 背包问题:

「力扣」第 416 题:分割等和子集(中等);
「力扣」第 474 题:一和零(中等);
「力扣」第 494 题:目标和(中等);
「力扣」第 879 题:盈利计划(困难);
「力扣」上的 完全背包问题:

「力扣」第 322 题:零钱兑换(中等);
「力扣」第 518 题:零钱兑换 II(中等);
「力扣」第 1449 题:数位成本和为目标值的最大数字(困难)。
这里要注意鉴别:「力扣」第 377 题,不是「完全背包」问题。

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/partition-equal-subset-sum/solution/0-1-bei-bao-wen-ti-xiang-jie-zhen-dui-ben-ti-de-yo/

贪心算法:优先放入平均价值最高的物品。

本题通过实际的案例,发现在这里贪心算法不可以得到全局最优解。

20190628225225471

通过背包问题,引入动态规划的解决办法。

背包容量c固定,具有重量和价值特征的n种物品,挑出0-n个物品,装进背包,使得背包装入的物品总价值最高。

image-20210109141301474

上图表示了0-1背包问题的状态转移方程。

F(n,c):将n个物品装进容量为c的背包,使得价值最大。

F(i,c)=max( F(i-1,c) , v(i) + F( i-1,c- w(i) ) )

F(i-1,c):第i个物品不放进背包中。

F( i-1,c- w(i) ) :第i个物品放进背包中,相应的,当前的背包容量=背包容量 - 物品i的重量w(i)。

(1)递归方法
public class p9_ex5_1_1 {
    public int knapsack01(int[] w, int[] v, int C) {
        int n = w.length;
        //用[0,1,... ...,index]的物品来填充体积为c的背包的最大价值
        // n-1 是说 物品 0到n-1
        return bestValue(w, v, n - 1, C);
    }

    private int bestValue(int[] w, int[] v, int index, int c) {
        // 边界条件
        // 在调用过程中,index是逐渐减少的,容量c也是逐渐减少的。
        if (index < 0 || c < 0) {
            return 0;
        }
        //第index个物品不放入背包里。
        int res = bestValue(w, v, index - 1, c);
        // 判断剩余容量与w[index] 判断第 index 个物品的体积是否 小于等于背包的剩余容量。
        // 否则直接返回上面得到的res。
        if (w[index] <= c) {
            //第index个物品放入背包里。
            res = Math.max(res, v[index] + bestValue(w, v, index - 1, c - w[index]));
        }
        return res;
    }
}
(2)记忆搜索
import java.util.Arrays;

// 记忆化搜索
public class p9_ex5_1_1_1 {
    int[][] memo;

    public int knapsack01(int[] w, int[] v, int C) {
        int n = w.length;
        // 这里的初始化 容量是 从0到c,是c+1个数。
        memo = new int[n][C + 1];
        for (int i = 0; i < n; i++) {
            Arrays.fill(memo[i], -1);
        }
        //用[0,1,... ...,index]的物品来填充体积为c的背包的最大价值
        // n-1 是说 物品 0到n-1
        return bestValue(w, v, n - 1, C);
    }

    private int bestValue(int[] w, int[] v, int index, int c) {
        // 边界条件
        // 在调用过程中,index是逐渐减少的,容量c也是逐渐减少的。
        if (index < 0 || c < 0) {
            return 0;
        }
        if (memo[index][c] != -1) {
            return memo[index][c];
        }
        //第index个物品不放入背包里。
        int res = bestValue(w, v, index - 1, c);
        // 判断剩余容量与w[index] 判断第 index 个物品的体积是否 小于等于背包的剩余容量。
        // 否则直接返回上面得到的res。
        if (w[index] <= c) {
            //第index个物品放入背包里。
            res = Math.max(res, v[index] + bestValue(w, v, index - 1, c - w[index]));
        }
        memo[index][c] = res;
        return res;
    }
}
(3)动态规划
import java.util.Arrays;

public class p9_ex5_3 {
    public static void main(String[] args) {
        int[] w = new int[]{1, 2, 3};
        int[] v = new int[]{6, 10, 12};
        int c = 5;
        System.out.println(knapsack01(w, v, c));
    }

    private static int knapsack01(int[] w, int[] v, int c) {
        int n = w.length;
        // 没有可供选择的物品
        if (n == 0) {
            return 0;
        }
        // c+1是为了遍历0到c这些重量。 c+1 个元素 遍历列元素。
        int[][] dp = new int[n][c + 1];
        // dp 第0行的元素是多少。
        // 因为下面的下面的双重for循环会使用i-1,所有先去计算得到i=0的数据。
        // dp[0][j] 是说考虑放入第0件物品。如果剩余容量≥w[0],则可以放入。
        for (int j = 0; j <= c; j++) {
            // 如果剩余容量j≥第0个物品的重量,那就可以将第0个物品放入背包,此时背包的价值为v[0]
            // 三目运算符
            dp[0][j] = j >= w[0] ? v[0] : 0;
        }
        for (int i = 1; i < n; i++) {
            for (int j = 0; j <= c; j++) {
                // dp[i][j]是指考虑0到i这些物品,且容积为j的背包,所得到的最大值是多少。
                // 1.不考虑第i件物品。
                dp[i][j] = dp[i - 1][j];
                // 剩余的容量j仍然可以将重量为w[i]的物品装进去。
                if (j >= w[i]) {
                    dp[i][j] = Math.max(dp[i][j], v[i] + dp[i - 1][j - w[i]]);
                }
            }
        }
        // dp初始化大小为[n][c+1]
        return dp[n - 1][c];
    }
}

[9 6.mp4]

(4)背包问题的优化

img

F(i,c)=max( F(i-1,c) , v(i) + F( i-1,c- w(i) ) )

F(i-1,c):第i个物品不放进背包中。

F( i-1,c- w(i) ) :第i个物品放进背包中,相应的,背包容量-物品i的重量w(i)。

第i行元素,只是依赖于第i-1行元素,因此理论上只保留两行元素即可。

代码如下:

public class p9_ex5_3_2_1 {
    public static void main(String[] args) {
        int[] w = new int[]{1, 2, 3};
        int[] v = new int[]{6, 10, 12};
        int c = 5;
        System.out.println(knapsack01(w, v, c));
    }

    private static int knapsack01(int[] w, int[] v, int c) {
        int n = w.length;
        if (n == 0) {
            return 0;
        }
        // 第i行元素,只是依赖于第i-1行元素,因此理论上只保留两行元素即可。
        int[][] dp = new int[2][c + 1];
        for (int j = 0; j <= c; j++) {
            dp[0][j] = j >= w[0] ? v[0] : 0;
        }
        // i j 还是正常的去遍历。但是dp的空间是限制在了两行元素。
        // dp[行的索引i或者i-1 % 2]
        for (int i = 1; i < n; i++) {
            for (int j = 0; j <= c; j++) {
                dp[i % 2][j] = dp[(i - 1) % 2][j];
                if (j >= w[i]) {
                    dp[i % 2][j] = Math.max(dp[i % 2][j], v[i] + dp[(i - 1) % 2][j - w[i]]);
                }
            }
        }
        return dp[(n - 1) % 2][c];
    }
}

[视频9-6 15min30s讲到了 0-1背包问题的变种]

但是并没有详细去引申。自己可以去研读一下:大雪菜的背包九讲+也可以加入大雪菜的寒假刷题班5元。但是实际面试应该够了,不会考的很深。

(1)完全背包问题

完全背包问题:每个物品可以无限次的使用。这里由于背包的容量有限制,所以实际上每个物品的个数也会被限制,所以可以将完全背包问题转化为0-1背包问题。

(2)多重背包问题

多重背包问题:每个物品不止1个,而是有num[i]个。感觉就是上面问题的拓展延伸。

(3)多维费用的背包问题

多维费用的背包问题:考虑体积和重量两个维度

(4)等等变形的问题

[9 7.mp4]

416. 分割等和子集

image-20210110100137128

对上面图片的解释:

题目要求:给定一个只包含正整数非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。那这样两个子集的元素和相等,那么所有元素遍历求和,除以2,得到目标值。目标值需要是整数。sum%2!=0

F(n,c)这里的c=sum/2。F(n,c)是将n个物品填满容量为c的背包。

F(i,c)=F(i-1,c)||F(i-1,c-w(i))。||的解释:因为要求结果是布尔值,那么只要这两个条件中一条满足,即可返回true。

F(i-1,c)是说第i个物品不装进背包。

F(i-1,c-w(i))是说将第i个物品装进背包。

伪代码:

1.遍历数组元素求和,sum%2!=0

2.边界条件:sum=0.sum<0.index<0.

3.业务代码

4.实际上,你考虑:sum/2在一个业务代码中满足了,那么剩余的元素和肯定也是sum/2。

(1)递归方法

递归会超时。

public class p9_ex7_416 {
    //用[0,......,index]的数组填充容量为sum的背包
    public boolean canPartition(int[] nums) {
        int n = nums.length;
        int sum = 0;
        // 首先,对输入的数组进行遍历求和。如果sum是偶数,则可以继续,否则直接返回false。
        for (int i = 0; i < n; i++) {
            sum = sum + nums[i];
        }
        // 如果sum不是偶数。那么就不能被平分。
        if (sum % 2 != 0) {
            return false;
        }
        // n-1 是对0到n-1的物品进行处理。
        // tryPartition解决了 0到n-1的物品 能否填充 sum/2 的背包。
        return tryPartition(nums, n - 1, sum / 2);
    }

    // 这里是使用nums[0...index]的物品,看是否能够完全填充一个容量为sum的背包
    private boolean tryPartition(int[] num, int index, int sum) {
        // 边界条件
        if (sum == 0) {
            return true;
        }
        // 边界条件
        if (sum < 0 || index < 0) {
            return false;
        }
        // 业务代码 F(i,c)=F(i-1,c)||F(i-1,c-w(i))
        //F(i-1,c)是说第i个物品不装进背包。
        //F(i-1,c-w(i))是说将第i个物品装进背包。
        return tryPartition(num, index - 1, sum) || tryPartition(num, index - 1, sum - num[index]);
    }
}
(2)记忆化搜索
import java.util.Arrays;

public class p9_ex7_416 {
    //memo[index][sum]用[0,......,index]的数组填充容量为sum的背包,是否可以填满
    //-1表示未填充,0表示填充不满,1表示可以填充
    int[][] memo;

    //用[0,......,index]的数组填充容量为sum的背包
    public boolean canPartition(int[] nums) {
        int n = nums.length;
        int sum = 0;

        // 首先,对输入的数组进行遍历求和。如果sum是偶数,则可以继续,否则直接返回false。
        for (int i = 0; i < n; i++) {
            sum = sum + nums[i];
        }
        // 如果sum不是偶数。那么就不能被平分。
        if (sum % 2 != 0) {
            return false;
        }
        memo = new int[n][sum / 2 + 1];
        for (int i = 0; i < n; i++) {
            Arrays.fill(memo[i], -1);
        }
        // n-1 是对0到n-1的物品进行处理。
        // tryPartition解决了 0到n-1的物品 能否填充 sum/2 的背包。
        return tryPartition(nums, n - 1, sum / 2);
    }

    // 这里是使用nums[0...index]的物品,看是否能够完全填充一个容量为sum的背包
    private boolean tryPartition(int[] num, int index, int sum) {
        // 边界条件
        if (sum == 0) {
            return true;
        }
        // 边界条件
        if (sum < 0 || index < 0) {
            return false;
        }
        if(memo[index][sum] != -1)
            return memo[index][sum]==1?true:false;
        memo[index][sum]=(tryPartition(nums,index-1,sum)||tryPartition(nums,index-1,sum-nums[index]))==true?1:0;
        return tryPartition(nums,index-1,sum)||tryPartition(nums,index-1,sum-nums[index]);  
    }
}

性能还是差一点。

image-20210110202958594
(3)动态规划

这个是看的力扣的题解:+感觉比视频要好理解的多。

其实我还是感觉记忆化搜索比动态规划容易理解。

public class p9_ex7_416_1_1_1 {
    public static void main(String[] args) {
        int[] nums = new int[]{1, 5, 11, 5};
        System.out.println(canPartition(nums));
    }

    public static boolean canPartition(int[] nums) {
        int n = nums.length;
        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum += nums[i];
        }
        if (sum % 2 != 0) {
            return false;
        }
        int c = sum / 2;
        // 这里的数组初始化后,默认值是false。
        boolean[][] dp = new boolean[n][c + 1];
        // 因为下面的句子会用到dp[i - 1][j]。所以先填表格第 0 行,第 1 个数只能让容积为它自己的背包恰好装满
        if (nums[0] <= c) {
            dp[0][nums[0]] = true;
        }
        for (int i = 1; i < n; i++) {
            for (int j = 0; j <= c; j++) {
                //不将第i件物品装进背包。
                dp[i][j] = dp[i - 1][j];
                // 下面的if可以删掉,不影响结果。
                if (nums[i] == j) {
                    dp[i][j] = true;
                    continue;
                }
                // 剩余容量可以装入第i件物品
                if (nums[i] < j) {
                    dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]];
                }
            }
        }
        return dp[n - 1][c];
    }
}

[3

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
应用背景为变电站电力巡检,基于YOLO v4算法模型对常见电力巡检目标进行检测,并充分利用Ascend310提供的DVPP等硬件支持能力来完成流媒体的传输、处理等任务,并对系统性能做出一定的优化。.zip深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值