zoukankan      html  css  js  c++  java
  • 51Nod1022 石子归并V2

    题目传送门

    四边形不等式第一题,口胡一下

    我们原来的方程式:f[i][j]=sum[i][j]+max(f[i][k]+f[k+1][j]){i<=k<j}

    那么,如果我们将最优的那个k记录下来,记为g[i][j],那么必然会有g[i][j-1]<=g[i][j]<=g[i+1][j]

    当然这个东西成立是需要条件的,就是f[i][j']+f[i'][j]<=f[i][j]+f[i'][j'] (i<=i',j'<=j) 

    博主太弱上面两个都不会证明(只会证明sum[i][j]+sum[i'][j']<=sum[i][j']+sum[i'][j]),下面内容来自百度百科:

    对s[i,j-1]≤s[i,j]≤s[i+1,j]的证明:
    设mk[i,j]=m[i,k]+m[k,j],s[i,j]=d
    对于任意k<d,有mk[i,j]≥md[i,j](这里以m[i,j]=min{m[i,k]+m[k,j]}为例,max的类似),接下来只要证明mk[i+1,j]≥md[i+1,j],那么只有当s[i+1,j]≥s[i,j]时才有可能有ms[i+1,j]≤md[i+1,j]
    (mk[i+1,j]-md[i+1,j])-(mk[i,j]-md[i,j])
    =(mk[i+1,j]+md[i,j])-(md[i+1,j]+mk[i,j])
    =(m[i+1,k]+m[k,j]+m[i,d]+m[d,j])-(m[i+1,d]+m[d,j]+m[i,k]+m[k,j])
    =(m[i+1,k]+m[i,d])-(m[i+1,d]+m[i,k])
    ∵m满足四边形不等式,∴对于i<i+1≤k<d有m[i+1,k]+m[i,d]≥m[i+1,d]+m[i,k]
    ∴(mk[i+1,j]-md[i+1,j])≥(mk[i,j]-md[i,j])≥0
    ∴s[i,j]≤s[i+1,j],同理可证s[i,j-1]≤s[i,j]
    证毕
    这样下来就可以优化了

    原来枚举k的时候需要从i~j现在只需要f[i][j-1]~f[i+1][j]就好了,这样是O(n^2)的(也不会证)

    #pragma GCC opitmize("O3")
    #pragma G++ opitmize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 2010
    using namespace std;
    int n,m,a[N],s[N],f[N][N],g[N][N];
    int main(){
        scanf("%d",&n); m=n<<1; memset(g,0x63,sizeof g);
        for(int i=1;i<=n;++i) scanf("%d",a+i),a[i+n]=a[i];
        for(int i=1;i<=m;++i) s[i]=s[i-1]+a[i],g[i][i]=0,f[i][i]=i;
        for(int k=1;k<=m;++k)
            for(int i=1,j;i+k<=m;++i){
                j=i+k;
                for(int x=f[i][j-1];x<=f[i+1][j];++x)
                    if(g[i][j]>g[i][x]+g[x+1][j]){ g[i][j]=g[i][x]+g[x+1][j]; f[i][j]=x; }
                g[i][j]+=s[j]-s[i-1];
            }
        for(int i=1;i<=n;++i) **g=min(**g,g[i][i+n-1]);
        printf("%d
    ",**g); memset(g,0,sizeof g);
        for(int i=1;i<=m;++i) g[i][i]=0,f[i][i]=i;
        for(int k=1;k<=m;++k)
            for(int i=1,j;i+k<=m;++i){
                j=i+k;
                for(int x=f[i][j-1];x<=f[i+1][j];++x)
                    if(g[i][j]<g[i][x]+g[x+1][j]){ g[i][j]=g[i][x]+g[x+1][j]; f[i][j]=x; }
                g[i][j]+=s[j]-s[i-1];
            }
        for(int i=1;i<=n;++i) **g=max(**g,g[i][i+n-1]);
        printf("%d
    ",**g);
    }


  • 相关阅读:
    LINQ使用的一点心得 子曰
    Extjs的grid的单元格中加载超链接和按钮 子曰
    关于建立“高保真模型”的必要性 子曰
    DHL:jQuery框架学习使用总结,插件,继续中...
    dhl:mvc用户登陆身份验证
    thickbox.js 及 将thickbox "close or esc key "改为 中文"关闭"
    在 jQuery 中如何判断对象是否存在
    jquery弹出层实例
    dhl:jquery select下拉框,checkbox,选择
    asp.net mvc 中"未找到路径“/favicon.ico”的控制器或该控制器未实现 IController。"
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/8312605.html
Copyright © 2011-2022 走看看