在寒假第一周的学习中,在三场训练赛之中,看到自己的不足,也同样学到了知识:
动态规划
这三场比赛中有很多与动态规划有关的题目,同样,在一次次的会面中我也对其有了了解:
一、洛谷P8647 分巧克力
在这道题目中,可以使用动态规划来求解最大的分巧克力块数。
具体做法如下:
定义一个二维数组dp,其中dp[i][j]表示前i块巧克力分成j份时的最大分巧克力块数。
初始化dp数组,将dp[0][0]设置为0,其他位置设置为一个较小的负无穷值,表示尚未计算出结果。
通过动态规划的递推公式来计算dp数组的值。对于每一块巧克力w[i],遍历所有的j,更新dp[i][j]的值:
·当前巧克力重量w[i]大于j份巧克力的最大重量k时,dp[i][j]等于dp[i-1][j],表示当前巧克力无法放入当前份中。
·当前巧克力重量w[i]小于等于j份巧克力的最大重量k时,dp[i][j]等于dp[i-1][j-1] + 1,表示当前巧克力可以放入当前份中,得到的分巧克力块数加一。
遍历dp数组的最后一行,找到最大的分巧克力块数,即为所求结果。
通过动态规划的方法,可以高效地求解分巧克力问题,并得到最优解。动态规划可以将问题划分为子问题,通过子问题的解来求解原问题,避免了重复计算,提高了算法的效率。
通过使用动态规划算法,可以高效地解决这道问题。
二、P1048 [NOIP2005 普及组] 采药
问题描述:
有一个体积为T的背包,和N份采药的清单。每份采药的花费时间和价值都不同。问在背包容量有限的情况下,能够采集到的最大价值是多少。
算法思路:
定义一个二维数组dp,dp[i][j]表示在前i份采药中,背包容量为j时能够达到的最大价值。
初始化dp数组为0。
采用动态规划的思想,遍历每一份采药:
如果当前采药的花费时间小于等于背包容量,则可以选择采集这份采药,更新dp[i][j]为max(dp[i-1][j], dp[i-1][j-cost[i]] + value[i]),其中cost[i]为当前采药的花费时间,value[i]为当前采药的价值。
如果当前采药的花费时间大于背包容量,则不能采集这份采药,dp[i][j]保持不变,即dp[i][j] = dp[i-1][j]。
遍历完所有采药后,dp[N][T]即为能够采集到的最大价值。
时间复杂度分析:
遍历每一份采药需要O(N)的时间复杂度,背包容量为T,因此总时间复杂度为O(N*T)。
该算法利用了动态规划的思想,通过拆分问题为子问题并利用子问题的最优解来求解整体问题的最优解,有效地解决了采药问题。
三、P8742 [蓝桥杯 2021 省 AB] 砝码称重
在该问题中,给定一组砝码的重量和数量,需要计算出可以通过这组砝码称重得到的不同重量的数量。
动态规划算法可以通过构建一个二维数组来解决该问题。假设砝码的重量范围为[1, W],其中W为最大的砝码重量,数量范围为[1, N],其中N为砝码的数量。那么可以构建一个二维数组dp,其中dp[i][j]表示使用前i个砝码可以称出重量j的方法数。
动态规划的状态转移方程如下:
当不使用第i个砝码时,dp[i][j] = dp[i-1][j],即前i-1个砝码可以称出重量j的方法数;
当使用第i个砝码时,dp[i][j] = dp[i-1][j-w[i]],其中w[i]表示第i个砝码的重量。因为使用第i个砝码后,需要找到前i-1个砝码可以称出重量为j-w[i]的方法数。
最终,dp[N][j]即为使用前N个砝码可以称出重量j的方法数。
通过计算dp数组的值,就可以得到砝码称重问题的解。因此,砝码称重问题运用了动态规划算法知识。