• HDU 2829 Lawrence


    $dp$,斜率优化。

    设$dp[i][j]$表示前$i$个数字切了$j$次的最小代价。$dp[i][j]=dp[k][j-1]+p[k+1][i]$。观察状态转移方程,可以发现是一列一列推导出来的。可以初始化第一列,然后算第二列,然后算第三列。

    暴力算的话时间复杂度是$O(n^3)$,需要优化。将$p[x][y]$换成带有$sum$的式子,一顿化简后,发现可以斜率优化。具体过程与HDU 3507差不多。不再赘述。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-10;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    template <class T>
    inline void read(T &x)
    {
        char c = getchar();
        x = 0;
        while(!isdigit(c)) c = getchar();
        while(isdigit(c))
        {
            x = x * 10 + c - '0';
            c = getchar();
        }
    }
    
    int n,m;
    long long a[1005],sum[1005],p[1005][1005],dp[1005][1005];
    int f1,f2,q[2000];
    
    bool delete1(int x,int a,int b,int c)
    {
        if(dp[b][x]-p[1][b]+sum[b]*sum[b]-dp[a][x]+p[1][a]-sum[a]*sum[a]<sum[c]*(sum[b]-sum[a])) return 1;
        return 0;
    }
    
    bool delete2(int x,int a,int b,int c)
    {
        if((dp[c][x]-p[1][c]+sum[c]*sum[c]-dp[b][x]+p[1][b]-sum[b]*sum[b])*(sum[b]-sum[a])<
        (dp[b][x]-p[1][b]+sum[b]*sum[b]-dp[a][x]+p[1][a]-sum[a]*sum[a])*(sum[c]-sum[b])) return 1;
        return 0;
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            if(n==0&&m==0) break; m++;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                sum[i]=sum[i-1]+a[i];
            }
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    int s=j,e=j+i-1;
                    if(e>n) continue;
                    if(i==1) { p[s][e]=0; continue; }
                    p[s][e]=p[s+1][e]+a[s]*(sum[e]-sum[s]);
                }
            }
    
            for(int i=1;i<=n;i++) dp[i][1]=p[1][i];
    
            for(int j=2;j<=m;j++)
            {
                f1=0; f2=0; q[f2]=j-1;
                for(int i=j;i<=n;i++)
                {
                    while(1)
                    {
                        if(f2-f1+1<2) break;
                        if(delete1(j-1,q[f1],q[f1+1],i)) f1++;
                        else break;
                    }
    
                    dp[i][j] = dp[q[f1]][j-1]+p[q[f1]+1][i];
    
                    while(1)
                    {
                        if(f2-f1+1<2) break;
                        if(delete2(j-1,q[f2-1],q[f2],i)) f2--;
                        else break;
                    }
    
                    f2++; q[f2]=i;
                }
            }
    
            printf("%lld
    ",dp[n][m]);
        }
        return 0;
    }
  • 相关阅读:
    2015年11月27日 野外生存(一)刀
    2015年11月26日 Java基础系列(五)异常Exception
    高斯混合模型(理论+opencv实现)
    K-means算法(理论+opencv实现)
    支持向量机(理论+opencv实现)
    《图像处理实例》 之 答题卡检测
    关于VS+ImageWatch在线调试问题
    关于W8.1不能安装VS2015(包括2017等)
    《图像处理实例》 之 车牌定位
    《opencv学习》 之 OTSU算法实现二值化
  • 原文地址:https://www.cnblogs.com/zufezzt/p/6349217.html
Copyright © 2020-2023  润新知