目录
今天我们来讲解一下C++算法中的动态规划,这是一个难点,大家一定要认真学习。
A. 走楼梯
楼梯一共有 𝑛 阶,上楼可以一步上一阶,也可以一步上二阶。
请求出走到第 𝑛 阶共有多少种不同的走法。
输入格式
一行一个整数 𝑛。
输出格式
一行一个整数表示答案。
样例输入
4
Copy
样例输出
5
Copy
数据规模
对于 100% 的数据,保证 1≤𝑛≤50。
思路:
这个题的数据范围是n小于等于50,所以这个题不能再用递归来做了,但是我们还有三种做法,一种是递推,一种是动态规划,还有一种是递归。
我们前面说了这个题不能再用一般的递归来做了,所以我们要再递归上再加上记忆化,也就是在递归的过程中记录每次求出来的新的值,这样就能避免重复计算,所以时间复杂度就减少了,就可以过掉大部分了,为什么是大部分而不是全部呢,因为这个题他的数据范围是n最大会等于50,所以我们可以推出这个题的最大值会远远超出int的最大值(2147483647)所以这个题的话我们要将用户自定义函数开到long long 才会通过这个题;
递推的做法呢,我们可以发现可以一步上一阶台阶,也可以一步上两阶台阶,所以除了第一阶台阶,别的台阶的上一步都可以是从上一阶台阶或者是从上两阶台阶上来的,那么就可以推出一个递推式:f[i]=f[i-1]+f[i-2],但我们需要首先将f[1]的值赋值为1,a[2]的值赋值为2,然后用一个for循环来进行递推,最后输出f[n]的值就是第n阶台阶的不同走法;
最后我们来讲动态规划的做法,但是我们仔细思考一下就可以发现,这个题的动态规划和递推的方法一样,所以这个题的动态规划和递推是一样的。
B. 最短路
#include <bits/stdc++.h>//递归+记忆化搜索
using namespace std;
int n;
long long f[10005];
long long a(int n) {
if(f[n]) {
return f[n];
}
if(n<=1) {
return 1;
}
f[n]=a(n-1)+a(n-2);
return f[n];
}
int main() {
cin>>n;
cout<<a(n)<<"\n";
return 0;
}
#include <bits/stdc++.h>//递推
using namespace std;
int n;
long long a[105];
int main() {
cin>>n;
a[1]=1,a[2]=2;
for(int i=3;i<=n;i++) {
a[i]=a[i-1]+a[i-2];
}
cout<<a[n]<<"\n";
return 0;
}
给定 𝑛 个点 𝑚 条边的有向图,每条边有个边权,代表经过这条边需要花费的时间,我们只能从编号小的点走到编号大的点,问从 1 号点走到 𝑛 号点最少需要花费多少时间?
输入格式
第一行两个整数 𝑛,𝑚。
接下来 𝑚m 行,每行三个整数 𝑢,𝑣,𝑤,表示存在一条从 𝑢 到 𝑣 的边权为 𝑤 的有向边。
保证存在一条 1 到 𝑛 的路径。
输出格式
输出一个数,表示答案。
样例输入
8 10
1 2 1
1 3 2
2 4 3
2 5 4
3 5 2
3 6 4
4 7 2
5 7 1
6 7 3
7 8 2
Copy
样例输出
7
Copy
数据规模
对于所有数据,保证 1≤𝑛≤,1≤𝑚≤,1≤𝑢<𝑣≤𝑛,1≤𝑤≤。
思路:
这个题我们依旧用动态数组vector来进行存图,但是这个题我们还要存一个权值,所以这个题在存图的时候与一般不太一样要edge[u].push_back({v,w});要这样存储图中边的信息,然后用一个dp数组来算最短路,首先我们要在将dp[2]到dp[n]的数赋值为一个较大的数,然后就开始计算,让每条边指向的边,在它本身和从1到i的之间的边的累加的和再加上这条边本身的权值之间取一个最小值,这样,每条边就都能求出来了,最后,我们只需要输出dp[n]的值就可以了。
最后
这就是动态规划(一)的讲解,希望大家可以学到一些知识,我们下期再见