四边形优化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;
}
原文地址:https://www.cnblogs.com/sssy/p/7197743.html