P3195 [HNOI2008] 玩具装箱题解
题目描述
P 教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。
P 教授有编号为 1⋯n 的 n 件玩具,第 i 件玩具经过压缩后的一维长度为 Ci。
为了方便整理,P 教授要求:
-
在一个一维容器中的玩具编号是连续的。
-
同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物。形式地说,如果将第 i 件玩具到第 j 个玩具放到一个容器中,那么容器的长度将为 x=j−i+k=i∑jCk。
制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为 x,其制作费用为 (x−L)2。其中 L 是一个常量。P 教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过 L。但他希望所有容器的总费用最小。
输入格式
第一行有两个整数,用一个空格隔开,分别代表 n 和 L。
第 2 到 第 (n+1) 行,每行一个整数,第 (i+1) 行的整数代表第 i 件玩具的长度 Ci。
输出格式
输出一行一个整数,代表所有容器的总费用最小是多少。
输入输出样例
输入 #1复制
5 4 3 4 2 1 4
输出 #1复制
1
说明/提示
对于全部的测试点,1≤n≤5×104,1≤L≤107,1≤Ci≤107。
思路
卡常n^2DP即可!!!
代码见下
#include<bits/stdc++.h>
using namespace std;
int n,l,c[50004],i,j;
long long f[50004],s,r[50004],b[50004];
int main(){
cin>>n>>l;
for(int i=1;i<=n;i++){
scanf("%lld",&c[i]);
r[i]=r[i-1]+c[i];
b[i]=r[i]+i;
}
//memset(f,62,sizeof(f));
f[0]=0;
for(i=1;i<=n;++i){
f[i]=1e18+7;
for(j=0;j<=i-2;j+=2){
s=(b[i]-b[j]-l-1);
s*=s;
if(s+f[j]<f[i]){
f[i]=s+f[j];
}
s=(b[i]-b[j+1]-l-1);
s*=s;
if(s+f[j+1]<f[i]){
f[i]=s+f[j+1];
}
//f[i]=min(f[i],f[j]+(b[i]-b[j]+i-j-1-l)*(b[i]-b[j]+i-j-1-l));
}
//if(j<i){
s=(b[i]-b[i-1]-l-1);
s=s*s;
if(s+f[i-1]<f[i]){
f[i]=s+f[i-1];
}
//}
//cout<<f[i]<<endl;
// i++;
// for(j=0;j<=i-2;j+=2){
// s=(b[i]-b[j]-l-1);
// s*=s;
// if(s+f[j]<f[i]){
// f[i]=s+f[j];
// }
// s=(b[i]-b[j+1]-l-1);
// s*=s;
// if(s+f[j+1]<f[i]){
// f[i]=s+f[j+1];
// }
// //f[i]=min(f[i],f[j]+(b[i]-b[j]+i-j-1-l)*(b[i]-b[j]+i-j-1-l));
// }
// //if(j<i){
// s=(b[i]-b[i-1]-l-1);
// s=s*s;
// if(s+f[i-1]<f[i]){
// f[i]=s+f[i-1];
// }
// //}
// //cout<<f[i]<<endl;
}
// int i=n;
// for(j=0;j<=i-2;j+=2){
// s=(b[i]-b[j]-l-1);
// s*=s;
// if(s+f[j]<f[i]){
// f[i]=s+f[j];
// }
// s=(b[i]-b[j+1]-l-1);
// s*=s;
// if(s+f[j+1]<f[i]){
// f[i]=s+f[j+1];
// }
// //f[i]=min(f[i],f[j]+(b[i]-b[j]+i-j-1-l)*(b[i]-b[j]+i-j-1-l));
// }
// //if(j<i){
// s=(b[i]-b[i-1]-l-1);
// s=s*s;
// if(s+f[i-1]<f[i]){
// f[i]=s+f[i-1];
// }
// //}
// //cout<<f[i]<<endl;
cout<<f[n]<<endl;
return 0;
}

浙公网安备 33010602011771号