算法优化之动态规划

动态规划严格上不是一种算法,而是一种优化,用于去除重复计算。

看一道简单的题目:

现在有编码方式:A->'1',B->'2'……Z->'26',现给出一个数串,要求有几种译码方式?

动态规划考虑问题的基础是分解问题,所以一种提倡的方式就是先写递归形式,再转成递推。

而分解问题的要点是,不要执着于要一口气得到最终解。所谓分解问题,就是降模,也就是在考虑n规模的时候,先考虑n-1的规模。

此时我们假设i规模的问题已解决【先将解决方法当成黑盒】,然后考虑i+1的规模。

带入此题,假设我们已经求出前i个字符的划分方式,在考虑第i+1个字符的时候,如果把第i+1个字符当成是被划分出来的单个字符,那么dp[i+1]=dp[i]。第二种情况,上述最大被划分的数是26,最多两位,所以两位划分的情况是10~26,特判一下Ai和Ai+1是否能构成满足条件的数,满足则dp[i+1]还需要累加上dp[i-1]。

代码:

#include
#include
using namespace std;
int dp[100];
char tar[100];
int main(){
    scanf("%s",tar+1);
    dp[0]=0;
    dp[1]=1;
    int len=strlen(tar+1);
    for(int i=2;i<=len;i++){
        dp[i]=dp[i-1];//单字符划分
        if((tar[i-1]=='1')||(tar[i-1]=='2')&&tar[i]<='6') {
            dp[i]+=dp[i-2];
        }
    }
    printf("%d",dp[len]);
}

不好意思上述代码有问题,现在给出修正代码:

修正1:字符串从索引1开始存储,前0个字符的划分方式是1,不是0。

修正2:字符长度为1的边界,直接打印1即可,不然在特判是否是两位中低位的时候会越界。

修正3:字符0,只能作为两位中的低位考虑,不能作为单字符划分,因此单字符的情况下的初始值为0而不是dp[i-1]。

#include
#include
using namespace std;
int dp[100];
char tar[100];
int main(){
    scanf("%s",tar+1);
    dp[0]=1;
    if(tar[1]=='0'){
        printf("0");
        return 0;
    } 
    dp[1]=1;
    int len=strlen(tar+1);
    if(len==1){
        printf("1");
        return 0;
    }
    for(int i=2;i<=len;i++){
        dp[i]=tar[i]=='0'?0:dp[i-1];//单字符划分
        if((tar[i-1]=='1')||(tar[i-1]=='2'&&tar[i]<='6')) {
            dp[i]+=dp[i-2];
        }
    }    
    printf("%d",dp[len]);
}

你可能感兴趣的:(算法优化之动态规划)