THUSC2016 成绩单
作者:互联网
成绩单
期末考试结束了,班主任 L 老师要将成绩单分发到每位同学手中。L老师共有 \(n\) 份成绩单,按照编号从 \(1\) 到 \(n\) 的顺序叠放在桌子上,其中编号为 \(i\) 的成绩单分数为 \(W_i\)。
成绩单是按照批次发放的。发放成绩单时,L 老师会从当前的一叠成绩单中抽取连续的一段,让这些同学来领取自己的成绩单。当这批同学领取完毕后,L 老师再从剩余的成绩单中抽取连续的一段,供下一批同学领取。经过若干批次的领取后,成绩单将被全部发放到同学手中。
然而,分发成绩单是一件令人头痛的事情,一方面要照顾同学们的心理情绪,不能让分数相差太远的同学在同一批领取成绩单;另一方面要考虑时间成本,尽量减少领取成绩单的批次数。对于一个分发成绩单的方案,我们定义其代价为:
\[a \times k+b \times \sum_{i=1}^{k}(\text{max}_i-\text{min}_i)^2 \]
其中 \(k\) 是分发的批次数,对于第 \(i\) 批分发的成绩单,\(\text{max}_i\) 是最高分数,\(\text{min}_i\) 是最低分数,\(a\) 和 \(b\)是给定的评估参数。
现在,请你帮助 L 老师找到代价最小的分发成绩单的方案,并将这个最小的代价告诉 L 老师。当然,分发成绩单的批次数 \(k\) 是由你决定的。
\(n \leq 50, a \leq 1500, b \leq 10, w_i \leq 1000\)
题解
https://blog.csdn.net/qq_39677783/article/details/86898654
考虑到这题的抽取方式:每次从中间抽取一段,然后两边的又会拼起来,所以区别于序列划分类问题,前缀DP的状态不够清晰无法转移,可以想到区间DP。
先设\(g(i,j)\)表示将\([i,j]\)这段区间的数全部消掉的最小代价,那么最终答案就是\(g(1,n)\)。但是这样会有问题:我们需要知道每次消去的\(\max_i\)和\(\min_i\)是多少,才能方便转移。那么我们可以这样做:首先对\(w_i\)离散化,假设\(tmp_i\)表示原数组\(w\)中第\(i\)小的数;对于一个\(g(i,j)\),我们可以枚举值域区间\([l,r]\),表示将\([i,j]\)这段区间里的数全部消掉之前最后一次消去的数都在值域范围\([l,r]\)当中。那么最后一次消去显然会产生\(a+b\times(tmp_r-tmp_l)^2\)的代价。那么接下来的问题就是:将区间\([i,j]\)中的数消到只剩下值域范围在\([l,r]\)中的数,最小代价是多少,不妨设其为\(f(i,j,l,r)\)。
这样一来我们\(g(i,j)\)的转移方程就有了:
\[g(i,j)=\min_{l\leq r}\{f(i,j,l,r)+a+b\times(tmp_r-tmp_l)^2\} \]
下面考虑\(f(i,j,l,r)\)的转移。一个显然的思路是
\[f(i,j,l,r)=\min_{i\leq k< j}\{f(i,k,l,r)+f(k+1,j,l,r)\} \]
然而很不幸这样做会漏掉一些情况。
正确的做法是:首先我们可以找到\([i,j]\)区间里左边第一个不在值域范围\([l,r]\)中的数的位置\(p\),以及右边第一个不在值域范围\([l,r]\)中的数的位置\(q\),如果存在这样的区间\([p,q]\)(如果不存在当然就不用管了),那么
\[f(i,j,l,r)=\min(g(p,q),\min\limits_{i\leq k< j}\{f(i,k,l,r)+f(k+1,j,l,r)\}) \]
好了,这两个转移方程出来之后,剩下的就是区间DP套路了。当然是枚举区间长度再枚举左端点做DP就行了。
时间复杂度\(O(n^5)\)
CO int N=60,inf=1e9;
int w[N],tmp[N];
int f[N][N][N][N],g[N][N];
int main(){
int n=read<int>(),a=read<int>(),b=read<int>();
for(int i=1;i<=n;++i) read(w[i]);
copy(w+1,w+n+1,tmp+1);
sort(tmp+1,tmp+n+1);
int all=unique(tmp+1,tmp+n+1)-tmp-1;
for(int i=1;i<=n;++i)
w[i]=lower_bound(tmp+1,tmp+all+1,w[i])-tmp;
for(int i=1;i<=n;++i){
g[i][i]=a;
for(int l=1;l<=all;++l)for(int r=l;r<=all;++r)
if(w[i]<l or w[i]>r) f[i][i][l][r]=a;
}
for(int len=2;len<=n;++len)for(int i=1,j=i+len-1;j<=n;++i,++j){
g[i][j]=inf;
for(int l=1;l<=all;++l)for(int r=l;r<=all;++r){
int p=0,q=0;
for(int t=i;t<=j;++t)
if(w[t]<l or w[t]>r) {p=t; break;}
for(int t=j;t>=i;--t)
if(w[t]<l or w[t]>r) {q=t; break;}
if(p and q) f[i][j][l][r]=g[p][q];
else f[i][j][l][r]=inf;
for(int k=i;k<j;++k)
f[i][j][l][r]=min(f[i][j][l][r],f[i][k][l][r]+f[k+1][j][l][r]);
g[i][j]=min(g[i][j],f[i][j][l][r]+a+b*(tmp[r]-tmp[l])*(tmp[r]-tmp[l]));
}
}
printf("%d\n",g[1][n]);
return 0;
}
标签:tmp,分发,min,int,leq,THUSC2016,成绩单 来源: https://www.cnblogs.com/autoint/p/13055033.html