递归,记忆化搜索和动态规划—比较及例题(c++)

1.递归

把问题拆分为子问题,从上到下深入,再逐层返回

特点:每次递归调用都要重新计算,时间复杂度高【O(2n)(指数级)】,效率低;

2.记忆化搜索:

与递归的不同:只计算需要的子问题,每次计算一个子问题后,将结果缓存,之后如果遇到相同问题,从缓存中查找结果;

3.动态规划:

与记忆化搜索差别:一次性计算完所有子问题并且缓存,遇见,查找;

4:代码比较:

示例题:B2064 斐波那契数列 - 洛谷

普通递归:

#include 
using namespace std;
int f(int n)
{
	if (n == 0)
		return 0;
	if (n == 1)
		return 1;
	return f(n - 1) + f(n - 2);
}
int main()
{
	int n = 0;
	cin >> n;
	vector arr(n, 0);
	for (int i = 0; i < n; i++)
	{
		cin >> arr[i];
		cout << f(arr[i] - 1) << endl;
	}
	return 0;
}

记忆化搜索:

#include 
using namespace std;
int arr[1000];
int f(int n)
{
	if (n == 0)
		return 0;
	if (n == 1 || n == 2)
		return 1;
	if (arr[n] != 0) // 如果已经计算过该值,则直接返回
		return arr[n];
	// 计算并保存结果到arr数组中
	arr[n] = f(n - 1) + f(n - 2);
	return arr[n];
}
int main()
{
	int n = 0;
	cin >> n;
	vector a(n, 0);
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
		cout << f(a[i] - 1) << endl;
	}
	return 0;
}

动态规划:

#include 
using namespace std;

int dp[1000] = {}; // 将数组名从arr改为dp,并初始化为0

int f(int n)
{
    dp[0] = 0;         // 初始化基础情况
    dp[1] = dp[2] = 1; // 初始化基础情况
    for (int i = 3; i <= n; ++i)
    { // 使用循环代替递归来填充dp数组
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n]; // 返回第n个斐波那契数
}
int main()
{
    int n = 0;
    cin >> n;
    vector arr(n, 0);
    for (int i = 0; i < n; i++)
    {
        cin >> arr[i];
        cout << f(arr[i] - 1) << endl;
    }
    return 0;
}

你可能感兴趣的:(动态规划,算法,c++)