1610:玩具装箱
时间限制: 1000 ms 内存限制: 524288 KB【题目描述】
原题来自:HNOI 2008
P 教授要去看奥运,但是他舍不得他的玩具,于是他决定把所有的玩具运到北京。
他使用自己的压缩器进行压缩。这个压缩器可以将任意物品变成一维,再放到一种特殊的一维容器中。P 教授有编号为 1…N 的 N 件玩具,玩具经过压缩后会变成一维,第 i 件件玩具压缩后长度为 Ci 。
为了方便整理,P 教授要求:
在一个一维容器中,玩具的编号是连续的;
如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物。形式地说,如果要将 i 号玩具到 j 号玩具 (i≤j) 放到同一个容器中,则容器长度不小于x=j−i+∑jk=iCk
制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为 x,其制作费用为 (X−L)2 ,其中 L是一个常量。
P 教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过 L。试求最小费用。
【输入】
第一行输入两个整数 N,L;
接下来 N 行,每行一个整数 Ci 。
【输出】
输出最小费用。
【输入样例】
5 4
3
4
2
1
4
【输出样例】
1
【提示】
数据范围与提示:
对于全部数据,1≤N≤5×104,1≤L,Ci≤107 。
sol:这题关键是暴力要写的尽量简洁些,式子才好推。。。
考虑如何使转移尽量简洁,Qzh[i]=Cost(1~i),使得Costi+=i,但这样会使得每次多一个,怎么办,把L+1就好了
方程就简洁了 dp[i]=dp[j]+Sqr(Qzh[i]-Qzh[j]-L),这样就很好推了
推出 j<k<i时 (为简洁把Qzh称作S)
若 dp[k]+S[k]2-dp[j]-S[j]2<=(S[i]-L)*(2*(S[k]-S[j]))成立,则 k 比 j 优
#include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0'); return; } write(x/10); putchar((x%10)+'0'); return; } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar(' ') const int N=50005; int n,L; ll Qzh[N]; ll dp[N]; inline ll Sqr(ll x) { return x*x; } int main() { int i,j; R(n); L=read()+1; for(i=1;i<=n;i++) { Qzh[i]=Qzh[i-1]+read(); } for(i=1;i<=n;i++) { Qzh[i]+=i; } memset(dp,63,sizeof dp); dp[0]=0; for(i=1;i<=n;i++) { for(j=0;j<i;j++) { dp[i]=min(dp[i],dp[j]+Sqr(Qzh[i]-Qzh[j]-L)); } } Wl(dp[n]); return 0; } /* input 5 4 3 4 2 1 4 output 1 */
#include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0'); return; } write(x/10); putchar((x%10)+'0'); return; } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar(' ') const int N=50005; int n,L; ll Qzh[N]; ll dp[N]; int Que[N]; inline ll Sqr(ll x) { return x*x; } inline bool Panduan(int j,int k,int i) // j<k<i { ll S1=dp[k]+Sqr(Qzh[k])-dp[j]-Sqr(Qzh[j]); ll S2=2*(Qzh[i]-L)*(Qzh[k]-Qzh[j]); return (S1<=S2)?(1):(0); } inline bool Panduan_Rev(int j,int k,int i) //j<k<i { ll S1=(dp[k]+Sqr(Qzh[k])-(dp[j]+Sqr(Qzh[j])))*(2*(Qzh[i]-Qzh[k])); ll S2=(dp[i]+Sqr(Qzh[i])-(dp[k]+Sqr(Qzh[k])))*(2*(Qzh[k]-Qzh[j])); return (S1>=S2)?(1):(0); } int main() { int i,j; R(n); L=read()+1; for(i=1;i<=n;i++) { Qzh[i]=Qzh[i-1]+read(); } for(i=1;i<=n;i++) { Qzh[i]+=i; } int Head=1,Tail=1; Que[1]=0; dp[0]=0; for(i=1;i<=n;i++) { while(Head<Tail&&Panduan(Que[Head],Que[Head+1],i)) Head++; int j=Que[Head]; dp[i]=dp[j]+Sqr(Qzh[i]-Qzh[j]-L); while(Head<Tail&&Panduan_Rev(Que[Tail-1],Que[Tail],i)) Tail--; Que[++Tail]=i; } Wl(dp[n]); return 0; } /* input 5 4 3 4 2 1 4 output 1 */