动态规划专题

动态规划将一个复杂问题分解为若干个子问题,通过综合子问题的最优解来获得原问题的最优解。

如果一个问题的最优解可以由其子问题的最优解有效地构造出来,那么称这个问题拥有最优子结构。一个问题必须拥有重叠子问题最优子结构,才能用动态规划去解决。

最大连续子序列和

给定一个数字序列:a1,a2,...,an,求 i, j (1<=i<=j<=n),使得ai+...+aj最大,输出这个最大和。

思路:设置数组dp[i]表示以A[i]为末尾的连续序列的最大和。

//A[i]已知
dp[0] = A[0];
for(int i=1;i<n;i++){
   dq[i] = max(A[i], A[i]+dp[i-1]);
}
int k=0;
for(int i=1;i<n;i++){
   if(dp[i]>dp[k]) k = i;
}

最长不下降子序列(LIS)

在一个数字序列中,找到一个最长的子序列(可以不连续),使得这个子序列是不下降(非递减)的。

思路:令dp[i]表示以A[i]结尾的最长不下降子序列长度。

//A[i]已知
int ans = -1;//存放最大dp[i]
for(int i=0;i<n;i++){
  dp[i] = 1;
  for(int j=0;j<i;j++){
     if(A[i]>=A[j] && (dp[i]<dp[j]+1))
        dp[i] = dp[j]+1;
  }
  ans = max(ans,dp[i]);
}

最长公共子序列(LCS)

给定两个字符串(或数字序列)A和B,求一个字符串,使得这个字符串是A和B的最长公共部分(子序列可以不连续)。

思路:令dp[i][j]表示字符串A的i号位和字符串B的j号位之前的LCS长度。

  • 若A[i]==B[j],则dp[i][j] = dp[i-1][j-1] + 1;
  • 若A[i] != B[j],则dp[i][j] = max{ dp[i][j-1], dp[i-1][j] }。
for(int i=0;i<=lenA;i++){
   dp[i][0] = 0;}
for(int i=0;i<=lenB;i++){
   dp[i][0] = 0;}
for(int i=1;i<=lenA;i++){
   for(int j=1;j<=lenB;j++){
       if(A[i]==B[j]) dp[i][j] = dp[i-1][j-1];
       else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
   }
}

最长回文字符串

给出一个字符串S,求S的最长回文子串的长度。

思路:令dp[i][j]表示S[i]至S[j]所表示的子串是否为回文子串,是为1,否为0。

for(int i=0;i<len;i++)
{    dp[i][i] = 1;
     if(i<len-1){
        if(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<=len;i++){
          int j = i+L-1;
          if(S[i]==S[j] && dp[i+1][j-1]==1){
              dp[i][j] = 1;
              ans = L;
          }
      }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鲸鲸爱柠檬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值