第四周学习总结

每周学习总结: 第四周

本周学习:动态规划的简单dp;

动态规划的三大步骤;

动态规划,就是利用历史记录,来避免我们的重复计算。而这些历史记录,我们得需要一些变量来保存,一般是用一维数组或者二维数组来保存(dp[])。下面是做动态规划题很重要的三个步骤,

定义数组元素的含义,我们会用一个数组,来保存历史数组,假设用一维数组 dp[]吧。这个时候有一个非常非常重要的点,就是规定你这个数组元素的含义,例如你的 dp[i] 是代表什么意思?

2、 找出数组元素之间的关系式(即状态转移方程),我觉得动态规划,还是有一点类似于高中学习时的归纳法的,当我们要计算 dp[n] 时,是可以利用 dp[n-1],dp[n-2]…dp[1],来推出 dp[n] 的,也就是可以利用历史数据来推出新的值,所以我们要找出数组元素之间的关系式,例如 dp[n] = dp[n-1] + dp[n-2],这个就是他们的关系式了。而这一步,也是最难的一步。
3、
找出初始值(即定义边界)。学过数学归纳法的都知道,虽然我们知道了数组元素之间的关系式,例如 dp[n] = dp[n-1] + dp[n-2],我们可以通过 dp[n-1] 和 dp[n-2] 来计算 dp[n],但是,我们得知道初始值,例如一直推下去的话,会由 dp[3] = dp[2] + dp[1]。而 dp[2] 和 dp[1] 是不能再分解的了,所以我们 必须要能够直接获得 dp[2] 和 dp[1] 的值,而这,就是所谓的初始值。

有了初始值,有了状态转移方程,再根据你定义的dp[]数组含义,就可以解题了;

一:最大子序列和问题;

根据上述三个步骤;
1、定义dp[i] 为数组前i个数的和;
2、如果第i个元素大于qiani个元素和,dp[i]=a[i].
得出状态转移方程 dp[i]=max(dp[i-1]+a[i],a[i])
3、定义边界dp[0]=a[0];
题就差不多解出来了。
代码:


  #include<iostream>
#include <cstdio>
#include <algorithm>   

using namespace std;

int a[11000],dp[11000];
int main()
{
   int n;
     
    while((cin >> n))
    {   
       if(n==0)  break;
    for(int i =0;i<n;i++)
    {
    cin>>a[i];
    }
    
    dp[0]=a[0];
    for(int i = 1;i<n;i++)
    {dp[i]=max(a[i],dp[i-1]+a[i]);
    }
    int k=0;
    for(int i =1;i<n;i++)
    {
        if(dp[i]>dp[k])
        k=i;
    }
 
    cout << dp[k]<< endl;
    }
}

二 、最长公共子序列(lcs)

问题描述;给出两个字序列a[],b[];求最长公共子序列。
三个步骤:
1、dp[i][j] 代表a 串从起点到i位置的字串 和 b 串从起点到j位置 的字串 的lcs;
2、建立状态转移方程:当a[i]==b[j] 时: dp[i][j]=dp[i-1][j-1]+1;
当 a[i]!=b[j] 时 : dp[i][j]=max(dp[i-1][j],dp[i][j-1]);

3、边界:dp[0][0]=0;
代码:

 #include<iostream>
#include <cstdio>
#include <algorithm>   
#include<cstring>
using namespace std;

int a[11000],b[11000],dp[11000][11000];
int main()
{   
     dp[0][0]=0;
     string a,b;
     int n=strlen(a);
     int m =strlen(b);
     cin>>a>>b;
    for(int i =1 ;i <=n;i++)
    for(int j=1;j<=m;j++)
    {
    if(a[i]==b[j])  
    dp[i][j]=dp[i-1][j-1]+1;
    else 
    dp[i][j]= max(dp[i-1][j],dp[i][j-1])
    cout<<dp[n][m];
    }

总的来说:最难的是第二个步骤,如果找到dp各个元素的关系,这个题也差不多就出来啦。
动态规划 多用数组来保留历史信息,以避免重复计算。
第一步的给数组定义 决定第二部建立状态转移方程的难易程度。所以,还是得走一步,看一步。

下周:老师发作业了;
老样子,每天1~2题 ,周末2 ~3题
🆗

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值