SOJ4509: Snowdrop修长廊 ( 斜率优化DP)

来源:互联网 发布:帝国cms多图上传插件 编辑:程序博客网 时间:2024/04/30 11:33

source: 点击打开链接


分析:一开始看到这题的时候就想到二维的区间dp,但是数据量根本不允许这么存,而且状态转移方程也不好写。在网上查了一下,才知道这是一道斜率优化DP。


网友Accept的斜率优化教程写得很好:

点击打开链接

我认为斜率优化的关键在于能假设两个状态j和k,写出在满足题目条件时描述他们之间关系的不等式,将不等式变形后用x,y做代换变成斜率形式,就可以使用斜率优化了。


AC代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn=200005;typedef long long ll;ll cost[maxn],dp[maxn],q[maxn],m;int head,tail;ll getDP(ll i,ll j){    return dp[j]+m+(cost[i]-cost[j+1])*(cost[i]-cost[j+1]);}ll getUP(ll j,ll k){    return dp[j]+cost[j+1]*cost[j+1]-(dp[k]+cost[k+1]*cost[k+1]);}ll getDOWN(ll j,ll k){    return 2*(cost[j+1]-cost[k+1]);}int main(){    ios::sync_with_stdio(0);    int T,n;    cin>>T;    while(T--){        cin>>n>>m;        for(int i=1;i<=n;i++)            cin>>cost[i];        cost[0]=cost[1];        sort(cost,cost+n);        memset(dp,0,sizeof(dp));        head=tail=0;        q[tail++]=0;        int lh=0;        for(ll i=1;i<=n;i++){            while(head+1<tail && getUP(q[head+1],q[head])<=cost[i]*getDOWN(q[head+1],q[head]))                head++;            dp[i]=min(getDP(i,q[head]),dp[i-1]+m);            while(head+1<tail && getUP(i,q[tail-1])*getDOWN(q[tail-1],q[tail-2])<=getUP(q[tail-1],q[tail-2])*getDOWN(i,q[tail-1]))                tail--;            q[tail++]=i;        }        cout<<dp[n]<<endl;    }    return 0;}





0 0
原创粉丝点击