zoukankan      html  css  js  c++  java
  • 四边形不等式优化

    四边形不等式优化

    填坑

    简介

    在动态规划问题中
    我们常遇到这样一类问题,它的dp方程长这样

    [f[i][j] = min { f[i][k] + f[k + 1][j]+cost[i][j] } ]

    这样我们的复杂度一般是(O(n^3))
    (a < b <= c < d)
    若有(f[a][c]+f[b][d]<=f[b][c]+f[a][d])
    则称这个东西满足四边形不等式
    定理
    设w函数为价值函数,对于上题来说(w(i,j) = cost[i][j])
    (w(i,j))满足(w(a,d)>=w(b,c))则称w关于区间包含关系单调
    定义s(i,j)表示dp(i,j)的最优决策点
    有如下定理

    1.若w同时满足区间包含单调性与四边形不等式则f也四边形不等式
    2.若f满足四边形不等式则s单调即(s(i,j)leq s(i,j+1)leq s(i+1,j+1))
    3.w满足四边形不等式当且仅当(w(i,j)+w(i+1,j+1)<=w(i,j+1) + w(i+1,j))

    怎么用呢?
    原先在dp的时候,枚举k的范围是((i,j)),转移复杂度是(O(n))
    若f满足四边形不等式的话那么(s[i][j-1] leq s[i][j] leq s[i+1][j])
    那么我们倒退i正推j,脑补一下,那么转移复杂度均摊(O(1))的了
    所以你只需要证明w为凸的且单调,dp时记录一下s,就可以降一维复杂度惹

    证明w满足四边形不等式

    不会(逃

    注意,可以用四边形不等式优化的dp转移方程并不是只有上述一种
    如:对于

    [f[i][j] = min { f[i-1][k] + w(k+1,j) } ]

    这个方程来说
    若证明w为凸的,那么f也为凸的,我们也可以用四边形不等式优化
    关键是怎么证明呀
    mlystcall
    我们可以知道如何绕过证明

    如果我们觉得一个方程能用四边形不等式优化,就把他的所有决策点,也就是s矩阵打印出来,观察一下在每行每列上是否单调,如果单调,就说明这个方程可以用四边形不等式优化

    其次要注意几点

    1.应注意决策点在那些范围内单调,这点在实际问题中应该很容易体现出来,比如在区间dp中的决策点(s[i][j] | j>i)的情况是不存在的
    2.注意枚举顺序

    那么剩下的就是
    打表检验单调性了
    据说与四边形不等式相关的优化,还有一个叫凸完全单调性,也是证明之后利用决策单调性优化。不会不会...

    附上石子合并的的代码
    w满足四边形不等式,因为此时相交区间和等与包含区间和
    其中求最大w的不能满足单调性?然后决策只在区间两断处取到?

    #include<cstdio> 
    #include<algorithm> 
    inline int read() {
        int x = 0,f = 1;
        char c = getchar();
        while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
        while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
        return x * f;
    } 
    const int maxn = 2007; 
    int dp[maxn][maxn],s[maxn][maxn],cnt[maxn]; 
    int sum[maxn]; 
    int dpm[maxn][maxn];
    int main () { 
        int n = read();
        for(int i = 1;i <= n;++ i) cnt[n + i] = cnt[i] = read(),sum[i] = sum[i - 1] + cnt[i]; 
        for(int i = n + 1;i <= n * 2;++ i) sum[i] = sum[i - 1] + cnt[i]; 
        for(int i = 1;i <= 2 * n;++ i) s[i][i] = i; 
        for(int i = n * 2 - 1;i >= 1;-- i) { 
            for(int j = i + 1;j <= n * 2;++ j) { 
                int tmp = 0x7fffffff,loc = 0; 
                dpm[i][j] = std::max(dpm[i][j - 1],dpm[i + 1][j]) + sum[j] - sum[i - 1]; 
                for(int k = s[i][j - 1];k <= s[i + 1][j];++ k) { 
                    if(tmp >dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]) { 
                        tmp = dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]; 
                        loc = k; 
                    } 
                } 
                dp[i][j] = tmp; 
                s[i][j] = loc; 
            } 
        } 
        int ansm = 0x7fffffff,ansx = 0;
        for(int i = 1;i <= n;++ i) {
            ansm = std::min(dp[i][i + n - 1],ansm) ; 
            ansx = std::max(dpm[i][i + n - 1],ansx) ; 
        }
        printf("%d
    %d",ansm,ansx);
        return 0;
    }
    
  • 相关阅读:
    # 机器学习算法总结-第七天(线性回归)
    # 机器学习算法总结-第六天(Adaboost算法)
    # 机器学习算法总结-第五天(降维算法PCA/SVD)
    #再谈 CVE-2017-10271回显POC构造
    # 机器学习算法总结-第四天(SKlearn/数据处理and特征工程)
    # 机器学习算法总结-第三天(支持向量机)
    # 机器学习算法总结-第二天(朴素贝叶斯、逻辑回归)
    # 机器学习算法总结-第一天(KNN、决策树)
    # weblogic CVE-2019-2615/2618(任意文件读取,任意文件上传)
    # CVE-2019-2725二次反序列化EventData Gadget POC/JdbcRowSetImpl POC构造
  • 原文地址:https://www.cnblogs.com/sssy/p/8998540.html
Copyright © 2011-2022 走看看