动态规划专题

登阶与子序列计数
本文探讨了经典的登阶问题及其动态规划解决方案,并深入解析了一道关于寻找字符串中能被3整除的子序列数量的算法题。通过详细的代码示例和数学逻辑解释,帮助读者理解递归和动态规划在解决这类问题中的应用。

https://blog.youkuaiyun.com/trochiluses/article/details/37966729

例一:有一段楼梯有10级台阶,规定每一步只能跨一级或两级,要登上第10级台阶有几种不同的走法?

 

 1 #include <bits/stdc++.h>
 2 #include<string>
 3 #include<string.h>
 4 #include<cstring>
 5 using namespace std;
 6 int solution(int n)  //递归做法
 7 {
 8     if(n<=2)
 9         return n;
10     else
11         return solution(n-1)+solution(n-2);
12 }
13 int dp[11]={0};
14 int solution1(int n)  //做法二   建数组存数据避重复
15 {
16     if(dp[n]!=0)
17         return dp[n];
18     else
19         return solution1(n-1)+solution1(n-2);
20 }
21 int main(){
22     int n;
23     cin>>n;
24     cout<<solution(n)<<endl;
25     dp[1]=1,dp[2]=2;
26     cout<<solution1(n)<<endl;
27 }

 

 

第一题:被3整除的子序列  

https://ac.nowcoder.com/acm/problem/21302

题解:https://blog.youkuaiyun.com/weixin_43922043/article/details/89164552

关键思路:

明确什么是子序列,类似于集合的东西,不需要连续

我们的关键是状态的变化

遍历字符串,把该字符加进来,这个序列中:与3取模为0,为1,为2的数目的变化。

dp[0]表示目前该序列中与3取模为0的子序列个数

dp[1]表示目前该序列中与3取模为1的子序列个数

dp[2]表示目前该序列中与3取模为2的子序列个数

我们把该字符分为三类:该字符与3取模为0,  该字符与3取模为1,  该字符与3取模为2

该字符与3取模为0:

dp[0]=dp[0]+dp[0]+1;//原来没加该字符与3取模为0的子序列数目+原来没加该字符与3取模为0的子序列加上该字符的组合+该字符单独组成的序列(长度为1)    //   3t*10+3r=3(t'+r)    假设该字符为3r,原序列为3t   该字符假设加在末尾   多了一个字符   子序列就变为3t*10+3r

dp[1]=dp[1]+dp[1];//原来没加该字符与3取模为1的子序列数目+原来没加该字符与3取模为1的子序列加上该字符的组合  // (3t+1)*10+3r

dp[2]=dp[2]+dp[2]//原来没加该字符与3取模为2的子序列数目+原来没加该字符与3取模为2的子序列加上该字符的组合   // (3t+2)*10+3r

该字符与3取模为1:

差不多的道理,懒得写,自己去看下面的公式

该字符与3取模为2:

差不多的道理

 

注意什么是序列,求的是什么

#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
int main(){
    char s[55];
    scanf("%s",s);
    int dp0=0,dp1=0,dp2=0;
    for(int i=0;i<strlen(s);i++){
        int t=s[i]-'0';
        int a=0,b=0,c=0;
        if(t%3==0){
            a=dp0*2+1;
            b=dp1*2;
            c=dp2*2;
        }
        if(t%3==1){
            a=dp0+dp2;
            b=dp1+dp0+1;
            c=dp2+dp1;
        }
        if(t%3==2){
            a=dp0+dp1;
            b=dp1+dp2;
            c=dp2+dp0+1;
        }
        dp0=a%mod;
        dp1=b%mod;
        dp2=c%mod;
    }
    cout<<dp0<<endl;
}

 

https://www.cnblogs.com/wkfvawl/p/9362287.html

 

第二题:删括号(未写)

https://ac.nowcoder.com/acm/problem/21303

https://blog.youkuaiyun.com/qq1013459920/article/details/89811749

 

转载于:https://www.cnblogs.com/Aiahtwo/p/11140112.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值