ACM程序设计基础第六周(区间dp、背包0-1问题)的学习总结与感悟


一、区间dp问题

1.问题概念:区间上进行动态规划,求解一段区间上的最优解。主要是通过合并小区间的 最优解进而得出整个大区间上最优解的dp算法(其与线性dp有很多并通之处,可以通过对问题先进行常规思考,再转化为通过线性dp求解思路思考,最后转化成区间dp
2.求解问题的思路:划分思路(大区间划分为小区间),求解每个小区间上的最优解,最后再合并成大区间的最优解
3.具体实现方法:枚举区间长度len为每次分割成的小区间长度(由短到长不断合并),内层枚举该长度下可以的起点,自然终点也就明了了。然后在这个起点终点之间枚举分割点,求解这段小区间在某个分割点下的最优解
4.模板代码


for(int len = 1;len<=n;len++){//枚举长度
        for(int j = 1;j+len<=n+1;j++){//枚举起点,ends<=n
            int ends = j+len - 1;
            for(int i = j;i<ends;i++){//枚举分割点,更新小区间最优解
                dp[j][ends] = min(dp[j][ends],dp[j][i]+dp[i+1][ends]+something);
            }
        }
}

5.三种模型
(1)石子合并模型(线性、圆形)(利用每个分割点来把大区间问题化为小区间问题)
(2)括号匹配模型(宴会穿礼服问题)
(3)抽卡片模型(不需要枚举区间,此类型只和左右边界有关系

二、背包0-1问题

1.问题描述:有N件物品和一个容量为V的背包。第i件物品的费用(即体积,下同)是w[i],价值是val[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大
2.解题思路:利用动态规划,阶段就是“物品的件数”,状态就是“背包剩下的容量”,那么很显然f [ i , v ] 就设为从前 i 件物品中选择放入容量为 v 的背包最大的价值。那么状态转移方程为:

f[i][v]=max{ f[i-1][v],f[i-1][v-w[i]]+val[i] }

状态转移方程解释:只考虑子问题“将前 i 个物品放入容量为 v 的背包中的最大价值”那么考虑如果不放入 i ,最大价值就和 i 无关,就是 f[ i - 1 ][ v ] , 如果放入第 i 个物品,价值就是 f[ i - 1][ v - w[i] ] + val[ i ],我们只需取最大值即可
3. 空间优化:上述状态表示,我们需要用二维数组,但是这种是可以优化的,考虑到可以对无用值的覆盖,所以只需要一维的滚动数组就可以解决问题,考虑到用f[ v ]来保存每层递归的值,由于我们求f[ i ][ v ] 的时候需要用到的是f[ i-1 ][ v] 和 f[ i-1 ][v - w[i] ] 于是可以知道,只要我们在求f[ v ]时不覆盖f[ v - w[i] ],那么就可以不断递推至所求答案。所以我们采取倒序循环,即v = m(m为背包总容积)

优化代码如下:

for i = 1..N

   for v = V..0

     f[ v ] = max{ f[ v ],f[ v-w[i] ]+val[ i ] };

另外:对数字位数(值)过大的情况(即超限),导致无法输入时,可以将变量定义为long long类型,也可以定义为字符串数组进行整体输入与输出

三、总结感悟

通过这周的学习,以及对一些经典例题的熟悉,思考编写;掌握了某些区间dp问题是和线性dp存在相同的关系,思考问题的思路基本一致,差别是在解决问题的方法上,具体区别如下:
线性dp:在一条直线上解决问题,对一条直线上的点(可以是一维的线性点,也可以二维的表格点)分析,找出他们的状态,以及与前后一些点的关系(状态转移方程)
区间dp:在线性dp的基础上,将多个点集中化,分析一个小区间上的点,即分析一些连续的点

其次,对于背包问题也有一定的了解(问题的描述可能与之前所学习过的贪心有一定的相似,但是在解决方法上截然不同)
背包问题贪心解决:一般都是可分割的物品,或者是存在装不满的情况(按照性价比装入,但最终实现不了最优化的结果)
背包问题动态规划解决(循环嵌套数永远比最优化的dp记录数组维数多1):物品不可分割,主要是分析第i件物品的选择(选与不选),其次是尤其需要注意其初始化时的细节
(1)要求恰好装满背包,那么在初始化时除了 f[0] 为 0 其它 f[1…V] 均设为 - ∞,这样就可以保证最终得到的 f[N] 是一种恰好装满背包的最优解
(2)如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将 f[0…V] 全部设为 0
理解:初始化的 f 数组事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满, 那么此时只有容量为 0 的背包可能 被价值为 0 的 nothing “恰好装满”,其它容量的背包均没有合法的解,属于未 定义的状态,它们的值就都应该是 - ∞了。如果背包并非必须被装满,那么任何 容量的背包都有一个合法解“什么都不装”,这个解的价值为 0,所以初始时状 态的值也就全部为 0 了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM-ICPC(国际大学生程序设计竞赛)是一项全球性的大学生程序设计比赛,每年吸引来自世界各地的顶尖大学代表队参与。ACM-ICPC竞赛的核心内容是团队编程和问题解决能力。 首先,ACM-ICPC竞赛对参赛选手的编程能力要求很高。参赛队伍需要在规定的时间内解决一系列的算法问题,这些问题常常包含复杂的数据结构和算法,要求选手在有限的时间内设计和实现高效的程序。 其次,ACM-ICPC竞赛强调团队协作。每个队伍由三名选手组成,他们需要分工合作,保持良好的沟通与协调,共同解决问题。团队成员需要相互理解、相互信任,快速地协商和决策,同时要保持高效的任务分配和时间管理。 此外,ACM-ICPC竞赛也需要选手具备良好的问题解决能力。这些问题往往是实际应用或理论推导相关的,选手需要从数学、计算机科学和算法等多个角度出发,找到最佳解决方案。在面对问题时,选手需要对问题进行分析、抽象和建模,运用各种算法和数据结构进行解决。 对于参赛选手来说,ACM-ICPC提供了一个学习与交流的平台。在比赛中,选手可以接触到不同国家和地区的优秀程序设计人才,学习他们的思维方式和编程技巧。同时,ACM-ICPC还举办了一系列的培训和研讨会,让选手有机会深入了解计算机科学和算法领域最新的研究成果。 总之,ACM-ICPC国际大学生程序设计竞赛是一个挑战性与学习性兼具的比赛。它要求选手具备扎实的编程技能、团队合作能力和问题解决能力。参与此竞赛不仅可以锻炼自己的编程能力,还能与全球的顶尖程序设计人才进行交流,拓宽自己的视野和思维方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值