hdu-3480-Division-dp-斜率优化

来源:互联网 发布:淘宝网怎么找店主 编辑:程序博客网 时间:2024/05/16 06:34

题意就是:一段区间的值就是max-min的平方,求n个点分成m线段的最小值

基本的DP式子是dp[i][x]=dp[j][x-1]+(a[i]-a[j+1])^2

然后用斜率优化

yj=dp[j][x-1]+a[j+1]^2

xj=2*a[j]

不等式为(yj-yk)/(xj-xk)<=a[i];


代码:

#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>using namespace std;#define maxn 11111int n,m;int a[maxn];int sum[maxn];int dp[maxn][maxn];int tot;int gg[maxn];int getDP(int i,int j,int x) {    return dp[j][x-1]+(a[i]-a[j+1])*(a[i]-a[j+1]);}int getUP(int j,int k,int x) {    return a[j+1]*a[j+1]+dp[j][x-1]-(a[k+1]*a[k+1]+dp[k][x-1]);}int getDOWN(int j,int k) {    return 2*(a[j+1]-a[k+1]);}int main(){    int t;    int kase=0;    scanf("%d",&t);    while(t--) {        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)            scanf("%d",&a[i]);        sort(a+1,a+n+1);        int head,wei;        for(int i=1;i<=n;i++) dp[i][1]=(a[i]-a[1])*(a[i]-a[1]);        for(int x=2;x<=m;x++) {            head=1;wei=2;            gg[1]=x-1;            for(int i=x;i<=n;i++) {                while(head+1<wei&&getUP(gg[head+1],gg[head],x)                      <=a[i]*getDOWN(gg[head+1],gg[head]))                    head++;                dp[i][x]=getDP(i,gg[head],x);//OK                while(head+1<wei&&getUP(i,gg[wei-1],x)*getDOWN(gg[wei-1],gg[wei-2])                      <=getUP(gg[wei-1],gg[wei-2],x)*getDOWN(i,gg[wei-1]))                    wei--;                gg[wei++]=i;            }        }        printf("Case %d: %d\n",++kase,dp[n][m]);    }    return 0;}



0 0