Print Article [HDU 3507] 斜率优化DP模板

http://acm.hdu.edu.cn/showproblem.php?pid=3507

View Code
const int MM = 555555;
#define debug puts("wrong")
#define mod 100000000
typedef __int64 int64;
int N,M;
int val[MM],sum[MM], dp[MM];
int head,tail,sq[MM];
/***************\
斜率优化DP  dp[i]=min(dp[j]+sqr(sum[i]-sum[j])+M | 1<=j<i)
对于队尾a b ,c插入 g[c,b]<=g[b,a] 则b对于最有策略没用
对于队首 b a,如有g[a,b]<=sum[i] 则a优于b,把b排除出队列
一开始压入0号构造的节点,防止边界条件,dp[N]为结果
对于斜率优化g[j,k]=(yj-yk)/(xj-xk)<const,则j优于k
\***************/ 
void get_data() {
    int i,j,k;
    sum[0]=0;
    for(i=1;i<=N;i++) {
        scanf("%d",&val[i]);
        sum[i]=sum[i-1]+val[i];
    }
}
int sqr(int x) {return x*x;}
int cal(int x,int y) { //x>y
    return (dp[x]+sqr(sum[x]))-(dp[y]+sqr(sum[y]));
}
bool ok(int b,int a,int c) { //a>b
    int tmp=cal(a,b);
    int tt=(sum[a]-sum[b])<<1;
    return tmp<=(sum[c]*tt);
}
bool ok1(int a,int b,int c) { //c>b>a
    int t1,t2;
    t1=cal(b,a)*((sum[c]-sum[b])<<1);
    t2=cal(c,b)*((sum[b]-sum[a])<<1);
    return t2<=t1;
}
void solve() {
    int i,j,k,tt;
    head=tail=dp[0]=0;
    sq[tail++]=0;
    for(i=1;i<=N;i++) {
        while(head+1<tail && ok(sq[head],sq[head+1],i)) head++;
        tt=sq[head];
        dp[i]=dp[tt]+sqr(sum[i]-sum[tt])+M;
        
        while(head+1<tail && ok1(sq[tail-2],sq[tail-1],i)) tail--;
        sq[tail++]=i;
    }
    printf("%d\n",dp[N]);
}

int main() {
    while(scanf("%d%d",&N,&M)!=EOF) get_data(),solve();    
    return 0;
}
原文地址:https://www.cnblogs.com/zhang1107/p/3046805.html