动态规划问题

动态规划

常见问题:

  • 基础,斐波那契数列f(n)=f(n-1)+f(n-2)
  • 背包问题
  • 打家劫舍
  • 股票问题
  • 子序列问题

一篇讲的蛮清楚的文章:http://t.csdhttp://t.csdn.cn/mwjCWn.cn/mwjCW

DP数组的定义以及下标的含义

递推公式

DP数组如何初始化

DP数组遍历顺序

HJ52 计算字符的编辑距离

字符串A: abcdefg

字符串B: abcdef

通过增加或是删掉字符 ”g” 的方式达到目的。这两种方案都需要一次操作。把这个操作所需要的次数定义为两个字符串的距离。

要求:
给定任意两个字符串,写出一个算法计算它们的编辑距离。

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>

using namespace std;

int main() {
    string str1, str2;
    while (cin >> str1 >> str2) {
        vector<vector<int>> dp(str1.size() + 1, vector<int>(str2.size() + 1, 0));
        for (int i = 1; i <= str2.size(); i++) dp[0][i] = i;//str1从0个字符变成str2的i个字符需要i个插入操作
        for (int i = 1; i <= str1.size(); i++) dp[i][0] = i;//str1从i个字符变成str2的0个字符也需要i个删除操作
        for(int i=1;i<=str1.size();i++){
            for (int j = 1; j <= str2.size(); j++) {
                int op1 = dp[i-1][j] + 1;//删除字符str1[i-1]
                int op2 = dp[i][j-1] + 1;//删除字符str2[j-1]
                int op3 = dp[i-1][j-1];//替换操作
                if(str1[i-1] != str2[j-1]){
                    op3++;
                }
                dp[i][j] = min(min(op1, op2), op3);//替换操作和删除操作取最小
            }
        }
        cout << dp[str1.size()][str2.size()] << endl;
    }
}

HJ61 放苹果

m个苹果放n个盘子,m<n的话,f(m,m),否则m苹果每个盘子都保证有苹果,和有空盘子的情况相加,进行递归。

在这里插入代码片#include<bits/stdc++.h>
using namespace std;
int sum=0;
int f(int m,int n){
    if(m==0)return 1;
    if(n==1)return 1;
    if(m<n) return f(m,m);
    return (f(m-n,n)+f(m,n-1));//放满盘子+不放满盘子
}
int main(){
    int m,n;
    cin>>m>>n;
    sum=f(m,n);
    cout<<sum;
    return 0;
}

HJ75 公共字串计算

暴力枚举法

#include<bits/stdc++.h>
using namespace std;
int main(){
    string a,b,temp;
    cin>>a>>b;
    if(a.length()>b.length()){
        temp=a;
        a=b;
        b=temp;
    }
    
    int max=0;
    for(int i=0;i<a.length();i++){
        int len=0;
        int k=i;
        for(int j=0;j<b.length();j++){
            //int l=j;
            if(a[i]==b[j]){
                len++;
                i++;
            }
            else{
                if(len>max) max=len;
                j-=len;
                len=0;
                i=k;
            }   
        }
        if(len>max) max=len;
        i=k;
    }
    cout<<max<<endl;
    return 0;
}

动态规划方法
在这里插入图片描述

动态数组dp[i][j]表示在b中以第i个字符结尾,a中以第j个字符结尾时的公共子串长度。maxlen表示最长公共子串的长度。遍历一遍两个字符串:
如果b中第i和a中第j个字符相同,则在以i-1和j-1结尾的子串后面加上i、j一位仍然是子串,因此dp[i][j]=dp[i−1][j−1]+1。
!注意连续!否则不连续,置为0,如果b中第i和a中第j个字符不相同,则以他们结尾的子串不可能相同,dp[i][j]=0。
如果更新后的dp[i][j]比maxlen大,则更新最大子串信息。

#include <bits/stdc++.h>
using namespace std;
int LCS(const string& str1,const string& str2) {
        // write code here
        int m = str1.size();
        int n = str2.size();
        // dp[i][j] str1前i个字符和str2前j个字符(以其为尾字符)的最长公共子串长度
        int dp[m+1][n+1];
        int maxlen = 0;
        //base case
        for(int i = 0; i <= m; ++i) dp[i][0] = 0;
        for(int j = 0; j <= n; ++j) dp[0][j] = 0;
        for(int i = 1; i <= m; ++i) {
            for(int j = 1; j <= n; ++j) {
                if(str1[i-1] == str2[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
                else dp[i][j] = 0;
                if(dp[i][j] > maxlen) {
                    maxlen = dp[i][j];
                }
            }
        }
        return maxlen;
}
int main(){
    string s1,s2;
    cin>>s1>>s2;
    cout<<LCS(s1,s2);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值