每日一题,今天lcs模板题,动态规划怎么这么难????

先练习一些简单的dp,慢慢来,主要是要找到状态转移方程是怎么写的,我也有时候想不到,哎这点就是动态规划最难的地方,慢慢来。

解决动态规划问题时,状态转移方程是非常重要的一部分,它描述了当前状态与之前状态之间的关系。

最长公共子序列问题中,我们可以通过以下步骤来推导状态转移方程

定义状态:我们定义dp[i][j]表示长度为i的A序列和长度为j的B序列的最长公共子序列的长度

考虑最后一步:在求解最长公共子序列的问题中,我们可以考虑最长公共子序列最后一个元素,即A[i]和B[j]

这样,我们可以将问题分解为两个子问题

如果A[i]等于B[j],那么最长公共子序列的最后一个元素就是A[i](或者B[j]),并且最长公共子序列的长度应该是dp[i-1][j-1] + 1。

如果A[i]不等于B[j],那么最长公共子序列的最后一个元素肯定不是A[i](或者B[j])

所以我们需要在A[1:i-1]和B[1:j]或者A[1:i]和B[1:j-1]中寻找最长公共子序列

写出状态转移方程:根据上述分析,我们可以得到状态转移方程:

如果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])

通过这样的推导过程,我们可以写出最长公共子序列问题的状态转移方程。

这个方程描述了当前状态与之前状态之间的关系,帮助我们在动态规划中有效地求解问题。

#include<iostream>
using namespace std;
//
//  1.设计状态(难):dp[i][j] 表示长度为i的A序列和长度为j的B序列的最长公共子序列的长度
//  2.状态转移方程(较难):
//  {
//    1.Ai=Bj 则 dp[i][j]=dp[i-1][j-1]+1
//    2.Ai!=Bj 则 dp[i][j]=msx(dp[i-1][j],dp[i][j-1])
// }
using ll =long long;
int n, m;
ll A[1005], B[1005];
int dp[1005][1005];
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)cin >> A[i];
    for (int i = 1; i <= m; i++)cin >> B[i];
    for(int i=1;i<=n;i++)
        for (int j = 1; j <= m; j++)
        {
            if (A[i] == B[j])dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);
            else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);//如果他们不相等的话//说明他们的最后一位肯定不是a[i]或者b[i]
            //所有我们只需要找到1到i-1的范围和1到j-1的访问去寻找最长的子序列//他们会根据前面的状态转移影响后面的状态转移
        }
    cout << dp[n][m];
    // if(a[i]>a[j]){
    //   c[i]=max(c[i],c[j]+a[i]);
    return 0;
}

本人也是小白,对应动态规划也不会,按照我现在的理解,我想跟我前面发的那个最大花之能量的博客有点相似的,只不过那个是以最后的元素结尾。

我们用一个数组来存放我们变化的值(也就是查找的共有的子序列的长度)

相等的时候,我们看是把它放入dp中取大的那个,然后不想等的情况,我们看最长公共子序列看是dp[i-1][j]和dp[i][j-1]看谁的大,我们就更新

也就是选A还是B的最长公共子序列,本人理解就这么多,听大佬说动态规划没有几百题是没有感觉的,我还需要多练.。然后如果我有错误的地方,请大家给我说出来,一起学习一起进步嘛。

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值