zoukankan      html  css  js  c++  java
  • 四边形优化dp

    拿石子合并这题为例

    设mid[i][j]是dp[i][j]的最优解的断点,即它左区间的右端点,那么mid[i][j-1]<=mid[i][j]<=mid[i+1][j],所以在求解dp[i][j]时,枚举k可以只枚举这两个值之间枚举就好,

    程序要先枚举区间长度,在枚举左端点,枚举每个区间长度时,他们的k总是只从1到n,只走一遍,所以这就相当于优化了一层,变成了O(n2)的。

    比如len长度为3时,dp[1][3]只会枚举mid[1][2]-mid[2][3],如上。然后dp[2][4]时,枚举mid[2][3]-mid[3][4]。以此类推。

    数据变大了,n^3过不了,考虑四边形优化

    code:

    #include <iostream>
    #include <cstdio>
    using namespace std;
    #define M 3003
    #define INF 0x7fffffff
    int n,f[M][M],sum[M][M],st[M],mid[M][M];
    int main() {
        cin>>n;
        for(int i=1; i<=n; i++)
            scanf("%d",&st[i]);
    
        for(int i=1; i<=n; i++) {
            f[i][i]=0;
            mid[i][i]=i;
            sum[i][i]=st[i];
            for(int j=i+1; j<=n; j++)
                sum[i][j]=sum[i][j-1]+st[j];
        }
    
        for(int len=2; len<=n; len++) 
        {
            for(int i=1; i<=n-len+1; i++) 
            {
                int j=i+len-1;
                f[i][j]=INF;
                for(int k=mid[i][j-1]; k<=mid[i+1][j]; k++) 
                {
                    if(f[i][j]>f[i][k]+f[k+1][j]+sum[i][j]) 
                    {
                        f[i][j]=f[i][k]+f[k+1][j]+sum[i][j];
                        mid[i][j]=k;
                    }
                }
            }
        }
        printf("%d
    ",f[1][n]);
        return 0;
    }
  • 相关阅读:
    CodeForces 706C Hard problem
    CodeForces 706A Beru-taxi
    CodeForces 706B Interesting drink
    CodeForces 706E Working routine
    CodeForces 706D Vasiliy's Multiset
    CodeForces 703B Mishka and trip
    CodeForces 703C Chris and Road
    POJ 1835 宇航员
    HDU 4907 Task schedule
    HDU 4911 Inversion
  • 原文地址:https://www.cnblogs.com/sssy/p/7197743.html
Copyright © 2011-2022 走看看