动态规划

10 篇文章 0 订阅
6 篇文章 0 订阅
  • 将一个复杂的问题分解成若干个子问题,通过综合子问题的最优解来得到原问题的最优解
  • 动态规划会将每个求解过的子问题的解记录下来,这样下一次碰到同样的子问题时,就可以直接使用之前记录的结果,而 不是重复计算
  • 可以用递归或者递推的写法实现,递归的写法又叫记忆化搜索
  • 重叠子问题:如果一个问题可以被分解成若干个子问题,且这些子问题会重复出现,就称这个问题拥有重叠子问题。 一个问题必须拥有重叠子问题,才能用动态规划去解决。
  • 最优子结构:如果一个问题的最优解可以由其子问题的最优解有效地构造出来,那么称为这个问题拥有的最有子结构。最优子结构保证了动态规划中的原问题的最优解可以由子问题的最优解推导而来
  • 动态规划与分治的区别:都是分解为子问题然后合并子问题得到解,但是分治分解出的子问题是不重叠的
  • 动态规划与贪心的区别:都有最优子结构,但是贪心直接选择一个子问题去求解,会抛弃一些子问题,这种选择的正确性需要用归纳法证明,而动态规划会考虑所有的子问题

参考文章:https://www.liuchuo.net/archives/tag/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92

最长回文子串问题

  • 给出一个字符串s,求s的最长回文字串的长度
    dp[i][j]表示s[i]到s[j]所表示的字串是否是回文字串。只有0和1
  • 递推方程:
    当s[i] == s[j] : dp[i][j] = dp[i+1][j-1]
    当s[i] != s[j] : dp[i][j] =0
    边界:dp[i][j] = 1, dp[i][i+1] = (s[i] == s[i+1]) ? 1 : 0
    -因为i、j如果从小到大的顺序来枚举的话,无法保证更新dp[i][j]的时候dp[i+1][j-1]已经被计算过(因为是从小到大遍历,i+1还没有计算出来)。因此不妨考虑按照字串的长度和子串的初试位置进行枚举,即第一遍将长度为3的子串的dp的值全部求出,第二遍通过第一遍结果计算出长度为4的子串的dp的值…这样就可以避免状态无法转移的问题
int len = s.length();
/*
    先把1和2长度的都初始化了
    说明:
        因为长度为1和2的时候,dp[i+1][j-1]并不代表他们的子回文串。
    举个例子:
        字符串长度为3的acb,dp[i+1][j-1]代表的是c是否为ab的子回文字符串,
        字符串长度为4的accb,dp[i+1][j-1]代表的是cc是否为ab的子回文串,
        字符串长度为2的时候ab,a与b中间没有数,所以长度为2或1时,dp[i+1][j-1]并不代表他们的子回文串,
        长度为1和2的字符串他们的子回文串就算自身
*/
int ans = 1;
for(int i = 0; i < len; i++) {
  dp[i][i] = 1;
  if(i < len - 1 && s[i] == s[i+1]) { 
    dp[i][i+1] = 1;
    ans = 2;
  }
}
//状态转移方程
for(int L = 3; L <= len; L++) {
  for(int i = 0; i + L - 1 < len; i++) {
    int j = i + L - 1;
    if(s[i] == s[j] && dp[i+1][j-1] == 1) {
      dp[i][j] = 1;
      ans = L;
    }
  }
}
printf("%d", ans);

背包问题

https://blog.csdn.net/a735311619/article/details/80213464

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值