hdu 2829 斜率DP

思路:dp[i][x]=dp[j][x-1]+val[i]-val[j]-sum[j]*sum[i]+sum[j]*sum[j];

其中val[i]表示1~~i是一段的权值。

然后就是普通斜率dp做法。

#include<cstdio>

#include<iostream>

#include<cstring>

#include<algorithm>

#include<cstring>

#define Maxn 1010

#define LL __int64

using namespace std;

LL dp[Maxn][Maxn],num[Maxn],sum[Maxn],val[Maxn];

int que[Maxn*10];

LL getleft(int x,int j,int k)

{

    return dp[j][x]-val[j]+sum[j]*sum[j]-(dp[k][x]-val[k]+sum[k]*sum[k]);

}

LL getright(int j,int k)

{

    return sum[j]-sum[k];

}

int main()

{

    int n,m,i,j,head,rear;

    while(scanf("%d%d",&n,&m)!=EOF,n||m){

        memset(dp,0,sizeof(dp));

        for(i=1;i<=n;i++){

            scanf("%I64d",num+i);

            sum[i]=sum[i-1]+num[i];

        }

        for(i=1;i<=n;i++){

            val[i]=val[i-1]+num[i]*sum[i-1];

            dp[i][0]=val[i];

        }

        for(j=0;j<m;j++){

            head=1,rear=0;

            que[++rear]=j;

            for(i=j+1;i<=n;i++){

                while(head<rear&&getleft(j,que[head+1],que[head])<sum[i]*getright(que[head+1],que[head]))

                    head++;

                dp[i][j+1]=dp[que[head]][j]+val[i]-val[que[head]]-sum[que[head]]*sum[i]+sum[que[head]]*sum[que[head]];

                while(head<rear&&getleft(j,i,que[rear])*getright(que[rear],que[rear-1])<=getleft(j,que[rear],que[rear-1])*getright(i,que[rear]))

                    rear--;

                que[++rear]=i;

            }

        }

        printf("%I64d\n",dp[n][m]);

    }

    return 0;

}

 

你可能感兴趣的:(HDU)