动态规划

动态规划专题

标签: ACM



动态规划思想

  • 动态规划问题是指可以将一个复杂的问题分解为若干个子问题,而子问题又可以分解成更子的问题(就像分割一样),通过最小的子问题的最优解一步一步往上,进而得到原问题的最优解
  • 和分治的区别:两者都是分解得到子问题,通过子问题的解得到原问题的解,但是分治的子问题之间是互相不干扰的(像归并排序,左右序列在人脑中是可以同时进行的),而动态规划的子问题可能是相互依赖的(可能会相互用到)

最大连续子序列和

  • 要求:严格连续,即下标不能像2,4,5…这样,而必须2,3,4,即2,4之间不能空一个a[3]
  • 思想:枚举右端点,对于每一个数,要么自己一个人组队,要么和前一个数组队,而前一个数也是同样可以自己组队或者和前一个数组队。故解法为:确定边界+状态转移方程递推: d p [ i ] = m a x { a [ i ] , d p [ i − 1 ] + a [ i ] } dp[i]=max\{a[i],dp[i-1]+a[i]\} dp[i]=max{a[i],dp[i1]+a[i]}因当前状态用到前一个状态的数据,故从左向右递推。

最长不下降子序列(LIS)

  • 要求:下标可以不连续
  • 思想:同"最大连续子序列和"枚举右端点,因下标可以不连续
    。故解法:确认边界+状态方程递推 d p [ i ] = m a x { 1 , d p [ j ] + 1 } , ( j = 0 , 1 , 2... i − 1 & & a [ i ] > a [ j ] ) dp[i]=max\{1,dp[j]+1\},(j=0,1,2...i-1\&\&a[i]>a[j]) dp[i]=max{1,dp[j]+1},(j=0,1,2...i1&&a[i]>a[j])

最长公共子序列(LCS)

  • 要求:两个string a,b,下标可以不连续
  • 思想:同样枚举两个右端点 i , j,dp[i][j]表示这两个端点之前的最长公共子序列 ,对于任意的i,j,

1. 当 a [ i ] = b [ j ] 时 , d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + 1 1.当a[i]=b[j]时,dp[i][j]=dp[i-1][j-1]+1 1.a[i]=b[j]dp[i][j]=dp[i1][j1]+1

2. 当 a [ i ] ! = b [ j ] 2.当a[i]!=b[j] 2.a[i]!=b[j]于时,区间扩大,但是公共序列没有增大,继承 d p [ i ] [ j ] = m a x { d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] } dp[i][j]=max\{dp[i-1][j],dp[i][j-1]\} dp[i][j]=max{dp[i1][j],dp[i][j1]}
在这里插入图片描述
当前状态用到左边一个状态和上面一个状态,故递推顺序为从上往下,从左往右,即大循环(i=0,n),循环里面为(j=0,n)

最长回文子串

  • 要求:一个字符串string a;
  • 思路:i,j为左右端点,dp[i][j]=1表示这个区间为回文串,遍历两个端点i,j;
    当 a [ i ] = b [ j ] 时 , d p [ i ] [ j ] = d p [ i + 1 ] [ j − 1 ] 当a[i]=b[j]时,dp[i][j]=dp[i+1][j-1] a[i]=b[j]dp[i][j]=dp[i+1][j1]
    当 a [ i ] ! = b [ j ] 时 , d p [ i ] [ j ] = 0 当a[i]!=b[j]时,dp[i][j]=0 a[i]!=b[j]dp[i][j]=0
    在这里插入图片描述
    能确定的边界是”"对角线dp[i][i]和dp[i][i+1],没有那种i,j遍历方式能实现状态转移。考虑到dp[i][j]和dp[i+1][j-1]之间有长度的差异,故使用遍历左端点+长度的方式
for(int i=0;i<s.size();i++){//预处理len=1,2
    dp[i][i]=1;
    if(!i){
    	if(s[i]==s[i-1]){
	        dp[i-1][i]=1;
    	    ans=2;
    	}
    }
}
for(int len=3;len<=s.size();len++){
    for(int i=0;i+len-1<s.size();i++){
        int j=i+len-1;//右端点
        if(s[i]==s[j]&&dp[i+1][j-1]){
            dp[i][j]=1;
            ans=len;
        }
    }
}
cout<<ans;

背包专题

01背包

  • 要求:n件物品,重w[i],价值v[i],背包最大承重v
  • 思路:很简单,一件物品可以拿也可以不拿,dp[i][j]表示前i件物品,在背包承重为j时能取得的最大值。可以转化为一维dp[j],遍历顺序同样画图可得出。

完全背包

  • 分析同01背包和上面四种模型
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值