其他分享
首页 > 其他分享> > 2021-10-24

2021-10-24

作者:互联网

技术分享 -- dp

一.导入

1. dp算法思想

dp算法是一种解决棘手问题的办法,它将问题分成小问题,随即将原问题转换为解决一系列的小问题。

2. dp种类

dp问题种类很多,可以细分为线性dp, 区间dp, 数位dp, 状压dp, 背包dp等等...

3.递推

递推就是指从已知的初始条件出发,依据某种递推关系,依次推出所要求的各中间结果及最后结果。简单来说,就是我现在能做什么,就现在做,做完然后再看看我能做哪些新的事情。

二.线性dp

例一:

题目:

东九楼梯有 N 阶,小猫咪从一楼想要回到223,它上楼可以一跳上一阶,也可以一跳上二阶。请你编一个程序,计算当小猫咪处于第n阶楼梯时,共有多少种不同的爬法。

想法:当小猫咪处于第n阶楼梯时,因为它最多一次能上2阶,那么,从此我们可以看出,小猫咪只能从n-1 或者 n-2 阶来。

我们假设小猫咪上n阶楼梯的跳法有f(n)种,可以推断出f(n) = f(n-1) + f(n-2)

下面附上代码:

int climb(int n) {
    int f[1000];
    f[0] = 1;  // 当处于地面时,只有一种情况,那就是不走
    f[1] = 1;
    for(int i = 2; i <= n; i++) {
        f[i] = f[i - 1] + f[i - 2];
    }
    return f[n];
}

例二:(思考题)

题目:

仍然是小猫咪上楼,但是小猫咪不一样了,它不仅一次可以跳一阶,二阶,还可以一次跳三阶,但是,它跳的方法不能和前一次的跳法一样,请你帮助小猫咪编写个程序来计算它处于第n阶楼梯时,共有多少种不同的爬法。

代码如下:

dp[1][1] = dp[2][2] = dp[3][1] = dp[3][2] = dp[3][3] = 1;
for (int i = 4; i <= n; i++) {             // i,j 代表的意思是跳了j 阶到达了第i阶
    for (int j = 1; j <= 3; j++) {
        for (int k = 1; k <= 3; k++) {
            if (j == k)continue;
            dp[i][j] += dp[i - j][k];
            dp[i][j] %= mod;
        }
    }
}
cout << (dp[n][1] + dp[n][2] + dp[n][3]) % mod;

三.二维dp

例一:

题目:(最长公共子序列)给定两个数组序列 a1 , a2 , . . . , an 和 b1 , b2 , . . . , bm,其中 n , m ≤ 1000 ,求两个数组的最长公共子序列。(公共子序列:指随意去掉数列中的元素所得到的结果)

代码如下:

if(a[0] == b[0]){
    f[0][0] = 1;
}
for(i = 0; i < n; i++) {
    for( j = 1; j < n; j++) {
        if(a[i] == b[j]) {
            f[i][j] = f[i-1][j-1] + 1;
        }
        else {
            if(f[i-1][j] > f[i][j-1]) {
                f[i][j] = f[i-1][j];
            }
            else {
                f[i][j] = f[i][j-1];
            }
        }
    }
} 

标签:24,10,int,2021,序列,楼梯,小猫咪,递推,dp
来源: https://blog.csdn.net/qq_50983179/article/details/120935418