线性动态规划方法论小结

Dynamic Programming

DP的前提:

有可解顺序:大问题可以拆成小问题。如有环的图上不能跑DAG最短路算法,无环时才能使用DP求出最短路。

  • 最优子结构性质:大问题的最优解必须时从小问题的最优解(而不是其他垃圾解)推出来的。
  • 无后效性:不用记录先前子结构的过程,只需记录结果。

DP三连

from 阮行止

我是谁 把实际局面表达成数学状态
我从哪里来 设计pull型的转移
我到哪里去 设计push型的转移

如果满足了上述条件就可以DP,写出状态转移方程之后,全体状态必定性能成一个DAG,DP的过程实际上就是在DAG上一次求出每个节点的value:大事化小,小事化了。

两种实现方式

按顺序递推?记忆化搜索
前者多用于push型的转移,后者多用于pull型的转移。使用前者实现的过程必定能用后者实现,反之亦然。
本质上,这两种方法反映了拓扑排序的两种实现方式。

线性DP举例

线性DP指的是在序列上执行的DP。

  • LIS问题
    给定数组a[],问最长的不下降的子序列的长度。
    朴素做法:
    三连:
    设计状态:记dp[x]:以a[x]结尾的LIS长度。
#include <iostream>
int n, a[100005];
void inp()
{
    scanf("%d", &n);
    for (int i = 1; i <=n; i++)
        scanf("%d", &a[i]);
}
void pull()
{
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < i; j++)//通过虚设一个零号元素,防止了某个元素最大不予赋值的情况,从而也免去了初始化为1的麻烦。
            if (a[j] <= a[i])
                dp[i] = max(dp[i], dp[j] + 1);
        for (int i = 1; i <= n; i++)
            printf("dp[%d] = %d\n", i, dp[i]);   
}

void push()
{
    for (int i = 0; i<= n; i++)
        for (int j = i + 1; j <= n; j++)
            if (a[i]<=a[j])
                dp[j] = max(dp[j], dp[i] + 1);
    for (int i = 1; i<=n ; i++)
        printf("dp[%d] = %d\n", i, dp[i]);
}

int main()
{
    inp();
    pull();
    return 0;
}

复杂度分析:

这个朴素算法的复杂度是 O ( n 2 ) O(n^2) 的。
第一轮循环枚举 x x ,这个复杂度不能省掉。
第二轮是找出这些地方(前面的,且不小于x)的最大dp值。

优化

要找出满足条件处的最大dp值是很困难的。
二分思路:如果能很快地实现检验过程,那么我们也能快速找到答案。
如何实现这个check?x应该接在谁后面?
随着x的增大,我们维护一个数组 r [ i ] : r[i]: 在已经走过的这些元素中,长度为i的LIS最小以什么数结尾。那么check§就很方便了:直接看p是否不超过a[x].

可二分性:LIS越长,结尾必然越大,r[i]单调上升。

int R[100005], ma;//在全局变量中声明的变量自动初始化为零
int bin_search(int x)//二分查找
{
    int l = 0, r = ma, mid;
    while (l != r)
    {
        mid = (l + r) /2 + 1;
        if (R[mid] <= x)    l = mid;
        else    r = mid - 1;
    }
    return l;
}
void opt()
{
    int len;
    for (int i = 1; i <= n; i++)
    {
        len = bin_search(a[i]) + 1; //求出以a[i]结尾的LIS最长能多长。
        dp[i] = len;
        ma = max(ma, len);  //  维护当前LIS长度
        R[len] = R[len] == 0? a[i]:min(R[len], a[i]); //维护R数组
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_45502929/article/details/106457333
今日推荐