bzoj4897「THUSC 2016」成績單(區間dp)
題目描述
期末考試結束了,班主任 L 老師要將成績單分發到每位同學手中。L老師共有 份成績單,按照編號從 到 的順序疊放在桌子上,其中編號為 的成績單分數為 。
成績單是按照批次發放的。發放成績單時,L 老師會從當前的一疊成績單中抽取連續的一段,讓這些同學來領取自己的成績單。當這批同學領取完畢後,L 老師再從剩餘的成績單中抽取連續的一段,供下一批同學領取。經過若干批次的領取後,成績單將被全部發放到同學手中。
然而,分發成績單是一件令人頭痛的事情,一方面要照顧同學們的心理情緒,不能讓分數相差太遠的同學在同一批領取成績單;另一方面要考慮時間成本,儘量減少領取成績單的批次數。對於一個分發成績單的方案,我們定義其代價為:
其中 是分發的批次數,對於第 批分發的成績單, 是最高分數,
是最低分數, 和 是給定的評估引數。 現在,請你幫助 L 老師找到代價最小的分發成績單的方案,並將這個最小的代價告訴 L 老師。當然,分發成績單的批次數 是由你決定的。
輸入格式
第一行包含一個正整數 ,表示成績單的數量。 第二行包含兩個非負整數 ,表示給定的評估引數。 第三行包含 個正整數 , 表示第 i 張成績單上的分數。
輸出格式
僅一個正整數,表示最小的代價是多少。
樣例
樣例輸入
10
3 1
7 10 9 10 6 7 10 7 1 2
樣例輸出
15
資料範圍與提示
:
把題目給的限制無腦丟進
方程就行了
表示
這段區間全部消完,且
這段值域不選的花費
表示
的答案
不難得到
的轉移
的轉移可以考慮末尾新增一個元素,反過來寫就是
#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;
}