玩具装箱

不难推出递推方程:dp[i]=min{dp[j]+(sum[i]+isum[j]jL1)^2}
 
不妨设A=i+sum[i],B=j+sum[j]+1。则递推式可以转化为:dp[i]=min{dp[j]+(A-B+L)^2}
 
接下来的部分留给读者自行推倒(主要是我懒得写了QAQ)
 
看代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=100000;
int n,L,f[maxn],q[maxn];
int c[maxn],sum[maxn];
int a(int i){
    return i+sum[i];
}
int b(int i){
    return i+sum[i]+1;
}
int x(int i,int j){
    return b(j)-b(i);
}
int y(int i,int j){
    return f[j]+b(j)*b(j)-f[i]-b(i)*b(i);
}
signed main(){
    cin>>n>>L;
    for(int i=1;i<=n;i++){
        scanf("%lld",&c[i]);
        sum[i]=sum[i-1]+c[i];
    }
    memset(f,0x3f,sizeof(f));
    int l=1,r=1;
    q[l]=0;f[0]=0;
    for(int i=1;i<=n;i++){
        while(l<r&&y(q[l],q[l+1])<=x(q[l],q[l+1])*2*(a(i)-L))l++;
        f[i]=f[q[l]]+(a(i)-b(q[l])-L)*(a(i)-b(q[l])-L);
        while(l<r&&y(q[r-1],q[r])*x(q[r],i)>=x(q[r-1],q[r])*y(q[r],i))r--;
        q[++r]=i;
    }
    cout<<f[n]<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/syzf2222/p/12386795.html