题目描述
期末考试结束了,班主任 L 老师要将成绩单分发到每位同学手中。L老师共有 n n n 份成绩单,按照编号从 1 1 1 到 n n n 的顺序叠放在桌子上,其中编号为 i i i 的成绩单分数为 W i W_i Wi。
成绩单是按照批次发放的。发放成绩单时,L 老师会从当前的一叠成绩单中抽取连续的一段,让这些同学来领取自己的成绩单。当这批同学领取完毕后,L 老师再从剩余的成绩单中抽取连续的一段,供下一批同学领取。经过若干批次的领取后,成绩单将被全部发放到同学手中。
然而,分发成绩单是一件令人头痛的事情,一方面要照顾同学们的心理情绪,不能让分数相差太远的同学在同一批领取成绩单;另一方面要考虑时间成本,尽量减少领取成绩单的批次数。对于一个分发成绩单的方案,我们定义其代价为:
a × k + b × ∑ i = 1 k ( max i − min i ) 2 a \times k+b \times \sum_{i=1}^{k}(\text{max}_i-\text{min}_i)^2 a×k+b×i=1∑k(maxi−mini)2
其中 k k k 是分发的批次数,对于第 i i i 批分发的成绩单, max i \text{max}_i maxi 是最高分数, min i \text{min}_i mini
是最低分数, a a a 和 b b b是给定的评估参数。 现在,请你帮助 L 老师找到代价最小的分发成绩单的方案,并将这个最小的代价告诉 L 老师。当然,分发成绩单的批次数 k k k 是由你决定的。
输入格式
第一行包含一个正整数 n n n ,表示成绩单的数量。 第二行包含两个非负整数 a , b a,b a,b ,表示给定的评估参数。 第三行包含 n n n 个正整数 , w i w_i wi表示第 i 张成绩单上的分数。
输出格式
仅一个正整数,表示最小的代价是多少。
样例
样例输入
10
3 1
7 10 9 10 6 7 10 7 1 2
样例输出
15
数据范围与提示
n ≤ 50 , a ≤ 1500 , b ≤ 10 , w i ≤ 1000 n \leq 50, a \leq 1500, b \leq 10, w_i \leq 1000 n≤50,a≤1500,b≤10,wi≤1000
s
o
l
u
t
i
o
n
solution
solution:
把题目给的限制无脑丢进
d
p
dp
dp方程就行了
f
[
l
]
[
r
]
[
u
p
]
[
d
o
w
n
]
f[l][r][up][down]
f[l][r][up][down]表示
[
l
,
r
]
[l,r]
[l,r]这段区间全部消完,且
[
u
p
,
d
o
w
n
]
[up,down]
[up,down]这段值域不选的花费
a
n
s
[
l
]
[
r
]
ans[l][r]
ans[l][r]表示
[
l
,
r
]
[l,r]
[l,r]的答案
不难得到
a
n
s
ans
ans的转移
a
n
s
[
l
]
[
r
]
=
m
i
n
k
,
a
,
b
{
f
[
l
]
[
k
]
[
a
]
[
b
]
+
a
n
s
[
k
+
1
]
[
r
]
}
ans[l][r]=min_{k,a,b}\{ f[l][k][a][b] +ans[k+1][r] \}
ans[l][r]=mink,a,b{f[l][k][a][b]+ans[k+1][r]}
f
f
f的转移可以考虑末尾添加一个元素,反过来写就是
f
[
l
]
[
r
]
[
m
i
n
(
a
,
v
[
r
]
)
]
[
m
a
x
(
a
,
v
[
r
]
)
]
=
m
i
n
k
{
f
[
l
]
[
k
]
[
a
]
[
b
]
+
g
[
k
+
1
]
[
r
−
1
]
}
f[l][r][min(a,v[r])][max(a,v[r])]=min_{k}\{f[l][k][a][b]+g[k+1][r-1]\}
f[l][r][min(a,v[r])][max(a,v[r])]=mink{f[l][k][a][b]+g[k+1][r−1]}
#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x],y = e[i].y;i;i = e[i].n,y = e[i].y)
#define P pair<int,int>
#define Pil pair<int,ll>
#define Pli pair<ll,int>
#define Pll pair<ll,ll>
#define pb push_back
#define pc putchar
#define mp make_pair
#define file(k) memset(k,0,sizeof(k))
#define ll long long
int rd()
{
int num = 0;char c = getchar();bool flag = true;
while(c < '0'||c > '9') {if(c == '-') flag = false;c = getchar();}
while(c >= '0' && c <= '9') num = num*10+c-48,c = getchar();
if(flag) return num;else return -num;
}
inline void chmin(int &a,int b){if(a>b)a=b;}
inline int min(int a,int b){return a<b?a:b;}
inline int max(int a,int b){return a>b?a:b;}
int n,A,B;
int a[60],tmp[60],tot;
int g[60][60],f[60][60][60][60];
int main()
{
n = rd();A = rd();B = rd();
rep(i,1,n) a[i] = tmp[i] = rd();tot = n;
sort(tmp+1,tmp+tot+1);
tot = unique(tmp+1,tmp+tot+1) - tmp - 1;
rep(i,1,n) a[i] = lower_bound(tmp+1,tmp+tot+1,a[i]) - tmp;
memset(f,10,sizeof(f));
memset(g,10,sizeof(g));
rep(i,1,n)
{
f[i][i][a[i]][a[i]] = 0;
g[i][i] = A;
g[i][i-1] = 0;
}
g[n+1][n] = 0;
rep(len,2,n)
rep(l,1,n-len+1)
{
int r = l+len-1,v = a[r];
rep(k,l,r-1) rep(a,1,tot) rep(b,a,tot)
{
int ta = min(a,v),tb = max(b,v);
chmin(f[l][r][ta][tb],f[l][k][a][b]+g[k+1][r-1]);
}
rep(k,l,r)
rep(a,1,tot) rep(b,a,tot)
chmin(g[l][r],f[l][k][a][b]+g[k+1][r]+A+B*(tmp[b]-tmp[a])*(tmp[b]-tmp[a]));
}
printf("%d\n",g[1][n]);
return 0;
}