动态规划

412 阅读1分钟

求解思路

  1. 递归 + 记忆化 -> 递推
  2. 状态的定义:opt[n],dp[n],fib[n]
  3. 状态的转移方程:opt[n] = best_of(opt[n-1], opt[n-2], opt[n-3] ...)
  4. 最优子结构

例:斐波拉契数列

递推公式

F[n] = F[n-1] + F[n-2]

普通递归 O(2^n)

    int fib(int n) {
        return n <= 1 ? n : fib(n - 1) + fib(n - 2);
    }

递推 O(n)

int fib2(int n) {
        int[] ints = new int[n + 2];
        ints[0] = 0;
        ints[1] = 1;
        for (int i = 2; i <= n; i++) {
            ints[i] = ints[i - 1] + ints[i - 2];
        }
        return ints[n];
    }

    // 只用三个变量求解,最节省空间
    int fib3(int n) {
        if (n <= 1) return n;

        int a = 0, b = 1, c = 0;
        for (int i = 1; i < n; i++) {
            c = a + b;
            b = c;
            a = b;
        }
        return c;

    }

例:爬格子

前方高能

类似这种从 A 走到 B 的,一次只能往下或者往右走一步,紫色块的地方走不通,求一共有多少种走法。

这种题和斐波拉契数列的解法差不多的,再来张灵魂绘画。

由于每次只能往下或者往右走一步,所以 A 到 B 的走法等于 C 到 B 加 D 到 B 的走法之和,而 D 到 B 的走法等于 E + G,C 到 B 等于 E + F ,就这样进入了无限套娃。

递推公式:
opt[i,j] = opt[i-1,j] = opt[i,j-1]

if opt[i,j] = '紫块':
    opt[i,j] = 0;
else:
opt[i,j] = opt[i-1,j] = opt[i,j-1]