1610:玩具装箱
时间限制: 1000 ms 内存限制: 524288 KB【题目描述】
原题来自:HNOI 2008
P 教授要去看奥运,但是他舍不得他的玩具,于是他决定把所有的玩具运到北京。
他使用自己的压缩器进行压缩。这个压缩器可以将任意物品变成一维,再放到一种特殊的一维容器中。P 教授有编号为 i 。
为了方便整理,P 教授要求:
在一个一维容器中,玩具的编号是连续的;
如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物。形式地说,如果要将
制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为 L是一个常量。
P 教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过 。试求最小费用。
【输入】
第一行输入两个整数 ,L;
接下来 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('\n') 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 */