zoukankan      html  css  js  c++  java
  • 四边形不等式优化-石子合并

    四边形不等式优化


    四边形不等式定义

    在oi历程中,常有如下的dp转移方程

    (f(i,j)=min(f(i,k)+f(k+1,j)+w(i,j))) ((i<=k<j))
    (f(i,j)=inf) ((i>j))
    (f(i,j)=0) ((i==j)​)

    根据转移,可以看出这是个(O(n^3))的时间复杂度

    但是 我们可以根据一些性质,优化部分转移,使其时间复杂度将至(O(n^2))

    四边形不等式的定义
    如函数(w),满足
    (w(i,j')+w(i',j)>= w(i,j)+w(i',j')) ((i<=i'<j<=j'))
    则称(w)是满足四边形不等式的,或称具有凸完全单调性
    可记作:交叉小于包含

    性质

    1. 若形同上式的(dp)方程中,(w)函数满足凸完全单调性,则(f)也满足凸完全单调性
    证明

    (i==i')(j==j')
    显然成立


    (i<i'=j<j')
    原式=(w(i,j')+w(j,j') <= w(i,j'))
    (k=min(t)(f(i,j')=f(i,t)+f(t+1,j')+w(i,j')))
    由于对称性(即下文中不等号右面的(j)(k)可以互换),则设(k<=j)

    (f(i,j)+f(j,j')<=f(i,j)+f(k+1.j)+w(i,j)+f(j,j')+w(j,j')) (因为是最有决策,不等号成立)
    (f(i,j)+f(j,j')<=f(i,j'))
    利用数学归纳法得证


    (i<i'<j<j')
    (y=min(t)(f(i',j)=f(i,t)+f(t+1,j')+w(i,j')))
    (z=min(t)(f(i,j')=f(i',t)+f(t+1,j)+w(i',j)))
    由于对称性(同上),可以设(z<=y)

    [f(i,j)+f(i',j')<=w(i,j)+w(i',j')+f(i',y)+f(i,z)+f(y+1,j')+f(z+1,j)$$; $$<=w(i,j)+w(i',j')+f(i',y)+f(i,z)+f(z+1,j')+f(y+1,j)$$; $$=f(i,j')+f(i',j)$$; 为什么这个东西成立呢? ]

    因为他的成立的必要条件是(f(i',y)+f(i,z)+f(y+1,j')+f(z+1,j)<=f(i',y)+f(i,z)+f(z+1,j')+f(y+1,j))

    可以看做是上述问题的规模缩小版。其最终情况会回归到前两种情景。


    1. 决策单调性

    我们加速dp所使用的就是决策单调性,四边形不等式是为了引出他

    设s(i,j)为f(i,j)的最有决策点

    那么有

    (s(i,j)<=s(i,j+1)<=s(i+1,j+1))

    证明

    (i>j)
    显然成立


    (i<j)

    为了方便叙述,我们令(f_k(i,j))表示(f(i,j))(k)时的决策值
    (f_{s(i,j)}(i,j)=f(i,j))

    由于f满足四边形不等式
    所以有
    (f(k,j)+f(k',j+1)<=f(k,j+1)+f(k',j) (k<k'<j)​)
    在不等式两边加上(w(i,j)+f(i,k-1)+w(i,j+1)+f(i,k'-1)​)
    便可得出
    (f_k(i,j)+f_{k'}(i,j+1) <= f_k(i,j+1)+f_{k'}(i,j)​)
    (f_k(i,j)-f_{k'}(i,j)<=f_k(i,j+1)-f_{k'}(i,j+1)​)

    可以发现,可以由左式推出右式
    由于在(s(i,j)​)右边的决策点来说,必有(f_k(i,j)>=f(i,j)​)
    还一定有 (f_s(i,j)(i,j+1)<=f_k(i,j+1)​)
    当然,(f(i,j)​)的决策点不一定是(s(i,j)​)
    但通过我们上面的证明,便可以确定,一定不小于(s(i,j)​)
    便证明出来了(s(i,j)<=s(i,j+1)​)
    剩下的一对也可以如此证明

    (s)满足上面的关系.则称s关于区间包含关系单调

    好(AO) 结束了上面的证明,便可以运用到(dp)中去了

    这玩意写了我一个晚上qwq,为了保证正确性,边写边证

    我们只需要处理这个决策点就可以啦

    根据证明,在确定一个大区间([i,j])时,([i,j-1])([i+1,j])的最有决策点已经确定了。直接在范围内枚举就好了

    关于时间复杂度么,不会证

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    
    using std::max;
    using std::min;
    
    const int maxn=300;
    
    int base[maxn];
    int dp[maxn][maxn],s[maxn][maxn];
    int MAX[maxn][maxn];
    
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&base[i]);
            base[i+n]=base[i];
        }
        for(int i=1;i<=n*2;i++)
            base[i]+=base[i-1];
        for(int i=1;i<=n*2;i++)
            s[i][i]=i;
        for(int l=2;l<=n;l++)
            for(int i=1;i<=(n*2)-l+1;i++)
            {
                int j=i+l-1;
                int x=s[i][j-1],y=s[i+1][j];
                dp[i][j]=0x7fffffff;
                MAX[i][j]=max(MAX[i][j-1],MAX[i+1][j])+base[j]-base[i-1];//最大值不满足四边形不等式,但最有决策一定出现在端点处
                for(int k=x;k<=y;k++)
                    if(dp[i][k]+dp[k+1][j]+base[j]-base[i-1]<dp[i][j])
                    {
                        dp[i][j]=dp[i][k]+dp[k+1][j]+base[j]-base[i-1];
                        s[i][j]=k;
                    }
            }
        int ansMin=0x7fffffff,ansMax=0;
        for(int i=1;i<n;i++)
            ansMin=min(ansMin,dp[i][i+n-1]),
            ansMax=max(ansMax,MAX[i][i+n-1]);
        printf("%d
    %d",ansMin,ansMax);
        return 0;
    }
    
  • 相关阅读:
    数据库系统概论习题集 第八章 数据库并发控制
    数据库系统概论习题集 第七章 数据库恢复技术
    数据库系统概论习题集 第六章 数据库设计
    数据库系统概论习题集 第五章 关系数据理论
    数据库系统概论习题集 第四章 关系系统及其优化
    数据库系统概论习题集 第三章 SQL语言
    【转载】【笔记】vue-router之路由传递参数
    【Dos】复制指定文件夹下所有文件到另外指定文件夹下
    【转载】Vue.js 安装及其环境搭建
    【转载】解决:'webpack-dev-server' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/10392691.html
Copyright © 2011-2022 走看看