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