本文内容
- 概述
- 从 Fibonacci 数列看“动态规划”思想
- 动态规划基础
- 动态规划步骤
- 动态规划意义
- 动态规划应用
- 备注
概述
在数据结构中,最经典的算法/问题是:Floyd 算法(最短路径)、哈夫曼编码和 Fibonacci(斐波那契数列),背包问题等等。但当时,这些经典仅仅是描述了一个问题的解决方法,没有对整个这类问题更深入的阐述。
而事实上,随着对问题理解深入,发现这些算法和问题都包含了“动态规划”的思想。在此思想基础上,对这些算法和问题可以进行重大改进——算法更简单、时间复杂度更小。
“动态规划(Dynamic Programming,DP)”对每个子问题只求解一次,将其结果保存在一张表中,从而避免每次遇到各个子问题时重新计算。“Programming”是指一种规划,在这里以及线性规划中,都是指使用一种表格化的解法,而不是指写计算机代码。
从 Fibonacci 数列看“动态规划”思想
下面用 C# 演示斐波那契数列的一般递归算法,以及利用“动态规划”思想的改进算法。
using System;
namespace Fibonacci
{
class Program
{
const int N = 6;
static int[] m = new int[N] { 1, 1, 0, 0, 0, 0 };
static void Main(string[] args)
{
Console.WriteLine("Fibonacci(5) = " + Fibonacci(5));
Console.WriteLine("Fibonacci(5) with Dynamic Programming = " + Fibonacci_DP(5, ref m));
Console.ReadKey();
}
/// <summary>
/// 时间复杂度 O(n!)
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
static int Fibonacci(int n)
{
if (n == 0 || n == 1)
return 1;
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
/// <summary>
/// 时间复杂度 O(n)
/// </summary>
/// <param name="n"></param>
/// <param name="m"></param>
/// <returns></returns>
static int Fibonacci_DP(int n, ref int[] m)
{
if (m[n] == 0)
m[n] = Fibonacci_DP(n - 1, ref m) + Fibonacci_DP(n - 2, ref m);
return m[n];
}
}
}