hdoj 3507 dp四边形不等式优化(其实用斜率dp更优)

来源:互联网 发布:美国网络中立 编辑:程序博客网 时间:2024/06/16 05:51

四边形不等式优化问题就不多说了。网上很多。

下面直接贴本题代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define MAX 505555using namespace std;__int64 n,M;__int64 dp[MAX],sum[MAX];struct Node{    int l,r,s;    Node(int ll=0,int rr=0,int ss=0):l(ll),r(rr),s(ss){}};Node que[MAX];int qf,qr;__int64 calv(int i,int j){    if(i>=j) return 1e16;  //返回无穷大    __int64 ans=(sum[j]-sum[i]);    ans=ans*ans+M;    return dp[i]+ans;}void Que(){    memset(dp,0,sizeof(dp));    int i,j;    qf=qr=0;    que[qr++]=Node(1,n,0);    for(i=1;i<=n;i++)    {        while(que[qf].r<i) qf++;        dp[i]=calv(que[qf].s,i);        int ll=0,rr;        while(qf!=qr) //队列不空,维护队列单调性        {            if(calv(que[qr-1].s,que[qr-1].l)>calv(i,que[qr-1].l)) qr--; //对于左端点,比较队尾决策点和i,若i更优,删除队尾元素            else            {                //比较区间右端点,若原决策比i更优,则i并入队尾决策区间,否则二分找转折点                if(calv(que[qr-1].s,que[qr-1].r)<calv(i,que[qr-1].r)) rr=que[qr-1].r+1;                else                {                    ll=que[qr-1].l,rr=que[qr-1].r;                    while(ll+1<rr)  //二分寻找转折点                    {                        int mid=(ll+rr)/2;                        if(calv(que[qr-1].s,mid)<calv(i,mid)) ll=mid;                        else rr=mid;                    }                }                //转折点作为队尾区间的右端点,[r,n]和决策i入队。退出while循环                que[qr-1].r=rr-1; //原来的队尾区间要修改                if(ll<=n)                {                    que[qr++]=Node(rr,n,i); //i并入决策区间                }                break;            }        }        if(qf==qr) que[qr++]=Node(i+1,n,i); //若队列为空,则区间[i+1,n]和决策点i入队    }    printf("%I64d\n",dp[n]);}int main(){    int i,j;    while(scanf("%I64d%I64d",&n,&M)!=EOF)    {        sum[0]=0;        for(i=1;i<=n;i++)        {            scanf("%I64d",&sum[i]);            sum[i]=sum[i-1]+sum[i];        }        Que();    }    return 0;}


 

0 0
原创粉丝点击