hdu 3480 斜率dp

思路:很普通的斜率dp

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Maxn 10010
#define LL int
using namespace std;
LL dp[Maxn][2],num[Maxn];
int que[Maxn*10];
inline LL getleft(int x,int j,int k)
{
    return dp[j][x]+num[j+1]*num[j+1]-(dp[k][x]+num[k+1]*num[k+1]);
}
inline LL getright(int j,int k)
{
    return 2*(num[j+1]-num[k+1]);
}
int main()
{
    int n,m,i,j,head,rear,t,Ca=0;
    int now,pre;
    scanf("%d",&t);
    while(t--){
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
            scanf("%d",num+i);
        sort(num+1,num+n+1);
        now=1,pre=0;
        for(i=1;i<=n;i++)
            dp[i][now]=(num[i]-num[1])*(num[i]-num[1]);
        for(j=1;j<m;j++){
            head=1,rear=0;
            que[++rear]=j-1;
            now=!now;
            pre=!pre;
            for(i=j;i<=n;i++){
                while(head<rear&&getleft(pre,que[head+1],que[head])<getright(que[head+1],que[head])*num[i])
                    head++;
                dp[i][now]=dp[que[head]][pre]+(num[i]-num[que[head]+1])*(num[i]-num[que[head]+1]);
                while(head<rear&&getleft(pre,i,que[rear])*getright(que[rear],que[rear-1])<=getleft(pre,que[rear],que[rear-1])*getright(i,que[rear]))
                    rear--;
                que[++rear]=i;
            }
        }
        printf("Case %d: %d\n",++Ca,dp[n][now]);
    }
    return 0;
}

 

posted @ 2013-10-14 21:34  fangguo  阅读(202)  评论(0编辑  收藏  举报