zoukankan      html  css  js  c++  java
  • [HDU2829] Lawrence

    [HDU2829] Lawrence

    题意简析

    定义一个序列的价值:序列中任意两个元素的积之和。

    给定义一个长度为n的序列,可以从中间断开m次,求如何断开,使得产生的多段序列的价值和最小。

    这种分段问题的单调性都比较明显

    \(dp[i][j]\)表示当前分到第\(i\)个点,分了\(j\)段的方案

    对于\(dp[i][j]\)的决策,\(j\)越大,决策点越大(分的段数越多,每段就越小)

    对于每个\(i\)进行一次决策单调性分治求解,复杂度$n^2 \ log \ n $

    const int N=1010;
    const ll INF=1ll<<50;
     
    int n,m;
    ll a[N],dp[N][N];
    int s[N],qs[N];
     
    void Solve(int p,int l,int r,int L,int R) {
        if(l>r) return;
        int mid=(l+r)>>1;
        ll mi=INF;
        int id=L;
        rep(i,L,R) {
            ll x=dp[i-1][mid-1]+1ll*(s[p]-s[i-1])*(s[p]-s[i-1])-(qs[p]-qs[i-1]);
            if(x<mi) mi=x,id=i;
        }
        dp[p][mid]=mi;
        Solve(p,l,mid-1,L,id);
        Solve(p,mid+1,r,id,R);
    }
    int main() {
        while(~scanf("%d %d",&n,&m) && n) {
            m++;
            rep(i,1,n) {
                a[i]=rd();
                s[i]=s[i-1]+a[i];
                qs[i]=qs[i-1]+a[i]*a[i];
            }
            memset(dp,63,sizeof dp);
            dp[0][0]=0;
            rep(i,1,n) Solve(i,1,min((int)i,m),1,i);
            printf("%lld\n",dp[n][m]/2);
        }
    }
    

    \[\ \]

    \[\ \]

  • 相关阅读:
    最高的牛
    激光炸弹(二维前缀和)
    汉诺塔问题
    费解的开关
    Hamilton路径(模板题)
    大臣的旅费【树型dp + 求树最长链】
    [蓝桥杯2018初赛]全球变暖
    操作集景
    [蓝桥杯2018初赛]倍数问题
    一些数学公式
  • 原文地址:https://www.cnblogs.com/chasedeath/p/11743234.html
Copyright © 2011-2022 走看看