Loading

算法关系

算法关系

CDQ与区间DP

划分区间使得独立的问题不仅可以使用CDQ,而且可以使用区间DP
其中CDQ分治是考虑两侧元素之间的点对点贡献
而区间DP是只关心整体值
但他们使用前提相同——区间可划分

DP的向前更新与向后更新

从DFS谈起

关于DFS搜索,有两种方式:最后计算答案与最后产生贡献。

以多重背包举例。

最后计算答案:

void DFS(int x,int v,int sum){
    if(x==n+1){ans=max(ans,sum);return;}
    for(int i=0;i<=m[x];i++)if(v+i*c[x]<=V)DFS(x+1,v+i*c[x],sum+i*w[x]);
}

最后产生贡献:

int DFS(int x,int V){
    if(x==n+1){return 0;}
    int tmp=0;
    for(int i=0;i<=m[x];i++)if(v+i*c[x]<=V)
        tmp=max(tmp,DFS(x+1,v+i*c[x])+i*w[x]);
    return tmp;
}

这两种搜索的复杂度是一样的,但后者可以使用记忆化搜索,而前者不行。

后者记忆化搜索可以直接变为DP。

在前者的基础上,纵向比较,即对于相同的 \(x,v\) 保留最大的 \(sum\),可以获得一个假的记忆化搜索。接着改变顺序变为递推,就可以变为一个刷表法DP,接着改变顺序就变为了填表法DP,即我们普遍背包问题解法。

这里对应了两种DP设计方式:

  • 最后贡献

  • 实时答案

以及两种DP实现方法:

  • 刷表法

  • 填表法

一般情况下,我们用的“实时答案”的DP,正如我们更容易想到“最后计算答案”的DFS,他更自然。

转化

刷表法与填表法一定是可以互转的,有逆运算的直接逆运算,无逆运算的直接枚举保证均摊复杂度,实在不行将所有转移存下来也可以做到。

在背包问题中,这两种DP设计方式是可以转化的。

在一般情况下:如果可以先枚举所有方案再解决,“实时答案”的方式

如果前面的决策与后面的无关,“最后贡献”的方式。

posted @ 2024-09-12 10:23  lupengheyyds  阅读(10)  评论(0)    收藏  举报