bzoj 1010 (单调决策优化)

   能够非常好的证明单调决策性质。用   记sum[i]=sigma(C[1],C[2].....C[k]);f[i]=sum[i]+i;  c=l-1;

有转移dp[i]=min( dp[j]+(f[i]-f[jk]-c)^2);  假死 有2个决策j<k, 对于i点。k决策更优秀 于是能够得到

dp[k]+(f[i]-f[k]-c)^2<dp[j]+(f[i]-f[j]-c)^2;

对于一个x>i  如果f[x]=f[i]+v;对于决策j,k。若决策k优于决策j  ,必定

 dp[k]+(f[x]-f[k]-c)^2<dp[j]+(f[x]-f[j]-c)^2;

于是dp[k]+(f[i]+v-f[k]-c)^2<dp[j]+(f[i]-v-f[j]-c)^2;

仅仅要2v(f[i]-f[k]-c)+v^2<2v(f[i]-f[j]-c)

优于v>0   f[k]>f[j]  这是必定成立的  ,所以能够非常好的证明单调决策性质。然后能够依据《1D/1D动态规划初步》论文的写法做。


#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <string>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int inf  = 0x3fffffff;
const int mmax = 500010;
LL C[mmax];
LL dp[mmax];
LL sum[mmax];
int n;
LL L;
struct node
{
    int l,r;
    int d;
    node() {}
    node(int l,int r,int d):l(l),r(r),d(d) {}
    void print()
    {
        printf("%d %d %d
",l,r,d);
    }
}Q[mmax];
LL sqr(LL x)
{
    return x*x;
}
void up(int i,int j)
{
    dp[i]=dp[j]+sqr(sum[i]-sum[j]+i-j-1-L);
}
bool ok(int i,int j,int d)
{
    return dp[d]+sqr(sum[i]-sum[d]+i-d-1-L)>=dp[j]+sqr(sum[i]-sum[j]+i-j-1-L);
}
int find(int l,int r,int j,int d)
{
    int mid;
    r++;
    while(l<r)
    {
        mid=(l+r)>>1;
        if(ok(mid,j,d))
            r=mid;
        else
            l=mid+1;
    }
    return r;
}
void make()
{
    int head=0,tail=0;
    dp[0]=0;
    Q[tail++]=node(0,n,0);
    for(int i=1;i<=n;i++)
    {
        while(Q[head].r<i)
            head++;
        if(Q[head].l<i)
            Q[head].l=i;
        up(i,Q[head].d);
        int tmp=0;
        while(head<tail)
        {
            if(ok(Q[tail-1].l,i,Q[tail-1].d))
            {
                tmp=Q[tail-1].l;
                tail--;
            }
            else
            {
                tmp=find(Q[tail-1].l,Q[tail-1].r,i,Q[tail-1].d);
                Q[tail-1].r=tmp-1;
                break;
            }
        }
        if(tmp<=n)
            Q[tail++]=node(tmp,n,i);
    }
}
int main()
{

    while(cin>>n>>L)
    {
        sum[0]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&C[i]);
            sum[i]=sum[i-1]+C[i];
        }
        make();
        printf("%lld
",dp[n]);
    }
    return 0;
}


原文地址:https://www.cnblogs.com/jzssuanfa/p/6937731.html