Description
期末考試結束了,班主任L老師要將成績單分發到每位同窗手中。L老師共有n份成績單,按照編號從1到n的順序疊
放在桌子上,其中編號爲i的成績單分數爲w_i。成績單是按照批次發放的。發放成績單時,L老師會從當前的一疊
成績單中抽取連續的一段,讓這些同窗來領取本身的成績單。當這批同窗領取完畢後,L老師再從剩餘的成績單中
抽取連續的一段,供下一批同窗領取。通過若干批次的領取後,成績單將被所有發放到同窗手中。然而,分發成績
單是一件使人頭痛的事情,一方面要照顧同窗們的心理情緒,不能讓分數相差太遠的同窗在同一批領取成績單;另
一方面要考慮時間成本,儘可能減小領取成績單的批次數。對於一個分發成績單的方案,咱們定義其代價爲:
其中,k是方案中分發成績單的批次數,對於第i批分發的成績單,〖max〗_i是最高分數,〖min〗_i是最低分數。
a,b是給定的評估參數。如今,請你幫助L老師找到代價最小的分發成績單的方案,並將這個最小的代價告訴L老師
。固然,分發成績單的批次數k是由你決定的。php
Input
第一行包含一個正整數n,表示成績單的數量。
第二行包含兩個非負整數a,b,表示給定的評估參數。
第三行包含n個正整數w_i,表示第i張成績單上的分數。ios
Output
僅一個正整數,表示最小的代價是多少。git
Sample Input
10ide
3 1spa
7 10 9 10 6 7 10 7 1 2code
Sample Output
15blog
【樣例數聽說明】
第1批:第2至4份成績單,落差值爲1,剩餘成績單爲76710712;ip
第2批:第4份成績單,落差值爲0,剩餘成績單爲767712;get
第3批:第1至4份成績單,落差值爲1,剩餘成績單爲12;string
第4批:剩餘的2份成績單,落差值爲1。
總代價爲4×3+(1^2+0^2+1^2+1^2)×1=15。
HINT
n<=50, a<=100, b<=10, w_i<=1000
思路:
注意是從中間抽,不然就太簡單了。
每次抽確定是一個子序列,且中間的空都是被抽空了。
設g[l][r]表示區間[l,r]被抽空的最小代價,f[l][r][i][j]表示區間[l,r]最後一抽最小值爲i,
最大值爲j,且強制要選a[l],a[r]的最小代價,
f[l][r][i][j]+g[r+1][R-1]→f[l][R][min(i,a[R])][max(j,a[R])])
f[l][r][i][j]+g[r+1][R]+A+B*(j-i)^2→g[l][R]
代碼+雙倍經驗
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<string> #include<algorithm> #include<iomanip> #include<cstdlib> #include<queue> #include<map> #include<set> #include<stack> #include<vector> #define ll long long using namespace std; inline int read() { int s=0,w=1; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();} while(isdigit(ch)) s=s*10+ch-'0',ch=getchar(); return s*w; } int n,mx,A,B,a[55],b[55],f[55][55][55][55],g[55][55]; void checkmin(int &x,int y) { x=x<y?x:y; } int main() { n=read(),A=read(),B=read(); for(int i=1;i<=n;i++) a[i]=b[i]=read(); sort(b+1,b+n+1),mx=unique(b+1,b+n+1)-b-1; for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+mx+1,a[i])-b; memset(f,0x3f3f3f3f,sizeof f),memset(g,0x3f3f3f3f,sizeof g); for(int i=1;i<=n;i++) f[i][i][a[i]][a[i]]=0,g[i][i]=A,g[i][i-1]=0; g[n+1][n]=0; for(int l=n;l;l--) for(int r=l;r<=n;r++) for(int i=1;i<=mx;i++) for(int j=i;j<=mx;j++) if(f[l][r][i][j]!=0x3f3f3f3f) { for(int nr=r+1;nr<=n;nr++) checkmin(f[l][nr][min(i,a[nr])][max(j,a[nr])],f[l][r][i][j]+g[r+1][nr-1]); for(int nr=r;nr<=n;nr++) g[l][nr]=min(g[l][nr],f[l][r][i][j]+g[r+1][nr]+A+B*(b[j]-b[i])*(b[j]-b[i])); } printf("%d",g[1][n]); return 0; }