Loading [MathJax]/extensions/TeX/mathchoice.js

THUSC2016 成绩单 和 LOJ3226 Greedy Pie Eaters

成绩单

期末考试结束了,班主任 L 老师要将成绩单分发到每位同学手中。L老师共有 n 份成绩单,按照编号从 1n 的顺序叠放在桌子上,其中编号为 i 的成绩单分数为 Wi

成绩单是按照批次发放的。发放成绩单时,L 老师会从当前的一叠成绩单中抽取连续的一段,让这些同学来领取自己的成绩单。当这批同学领取完毕后,L 老师再从剩余的成绩单中抽取连续的一段,供下一批同学领取。经过若干批次的领取后,成绩单将被全部发放到同学手中。

然而,分发成绩单是一件令人头痛的事情,一方面要照顾同学们的心理情绪,不能让分数相差太远的同学在同一批领取成绩单;另一方面要考虑时间成本,尽量减少领取成绩单的批次数。对于一个分发成绩单的方案,我们定义其代价为:

a×k+b×ki=1(maximini)2

其中 k 是分发的批次数,对于第 i 批分发的成绩单,maxi 是最高分数,mini 是最低分数,ab是给定的评估参数。
现在,请你帮助 L 老师找到代价最小的分发成绩单的方案,并将这个最小的代价告诉 L 老师。当然,分发成绩单的批次数 k 是由你决定的。

n50,a1500,b10,wi1000

题解

https://blog.csdn.net/qq_39677783/article/details/86898654

考虑到这题的抽取方式:每次从中间抽取一段,然后两边的又会拼起来,所以区别于序列划分类问题,前缀DP的状态不够清晰无法转移,可以想到区间DP。

先设g(i,j)表示将[i,j]这段区间的数全部消掉的最小代价,那么最终答案就是g(1,n)。但是这样会有问题:我们需要知道每次消去的maximini是多少,才能方便转移。那么我们可以这样做:首先对wi离散化,假设tmpi表示原数组w中第i小的数;对于一个g(i,j),我们可以枚举值域区间[l,r],表示将[i,j]这段区间里的数全部消掉之前最后一次消去的数都在值域范围[l,r]当中。那么最后一次消去显然会产生a+b×(tmprtmpl)2的代价。那么接下来的问题就是:将区间[i,j]中的数消到只剩下值域范围在[l,r]中的数,最小代价是多少,不妨设其为f(i,j,l,r)

这样一来我们g(i,j)的转移方程就有了:

g(i,j)=minlr{f(i,j,l,r)+a+b×(tmprtmpl)2}

下面考虑f(i,j,l,r)的转移。一个显然的思路是

f(i,j,l,r)=minik<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),minik<j{f(i,k,l,r)+f(k+1,j,l,r)})

好了,这两个转移方程出来之后,剩下的就是区间DP套路了。当然是枚举区间长度再枚举左端点做DP就行了。

时间复杂度O(n5)

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;
}

Greedy Pie Eaters

Farmer John 有 M 头奶牛,为了方便,编号为 1M。这些奶牛平时都吃青草,但是喜欢偶尔换换口味。Farmer John 一天烤了 N 个派请奶牛吃,这 N 个派编号为 1N。第 i 头奶牛喜欢吃编号在 [li,ri] 中的派(包括两端),并且没有两头奶牛喜欢吃相同范围的派。第 i 头奶牛有一个体重 wi,这是一个在 [1,106] 中的正整数。

Farmer John 可以选择一个奶牛序列 c1,c2,cK,并让这些奶牛按这个顺序轮流吃派。不幸的是,这些奶牛不知道分享!当奶牛 ci 吃派时,她会把她喜欢吃的派都吃掉——也就是说,她会吃掉编号在 [lci,rci] 中所有剩余的派。Farmer John 想要避免当轮到一头奶牛吃派时,她所有喜欢的派在之前都被吃掉了这样尴尬的情况。因此,他想让你计算,要使奶牛按 c1,c2,cK 的顺序吃派,轮到这头奶牛时她喜欢的派至少剩余一个的情况下,这些奶牛的最大可能体重(wc1+wc2++wcK)是多少。

对于全部数据,1N300,1MN(N1)2,1liriN,1wi106

题解

http://jklover.hs-blog.cf/2020/06/07/Loj-3226-Greedy-Pie-Eaters/#more

首先可以假定所有\binom{n}{2}个区间都对应了一头牛,没有给出的可以将其牛的重量看作 0 .

当某头牛要吃区间 [l,r]​ 时,若剩下的派大于 1​ ,可以先让其他牛吃到还剩一个,于是每头牛都恰好吃掉一个派.

f(l,r)​ 表示把 l,r​ 内的派吃完能获得的最大收益,转移时枚举最后被吃的派是 k​ ,

f(l,r)=\max_{l\le k\le r} f(l,k-1)+f(k+1,r)+g(l,r,k)

其中 g(l,r,k)=\max_{l\le x\le k\le y \le r} A_{x,y} ,表示用区间不超出 [l,r] 的牛吃掉第 k 个派能获得的最大收益.

转移时考虑 [l,r] 这个区间的贡献就行了.

g(l,r,k)=\max \lbrace A_{l,r},g(l+1,r,k),g(l,r-1,k) \rbrace

时间复杂度 O(n^3) .

CO int N=310;
int a[N][N],g[N][N][N],f[N][N];
int main(){
int n=read<int>();
for(int m=read<int>();m--;){
int w=read<int>(),l=read<int>(),r=read<int>();
a[l][r]=w;
}
for(int len=1;len<=n;++len)
for(int l=1,r=l+len-1;r<=n;++l,++r)
for(int k=l;k<=r;++k){
g[l][r][k]=max(a[l][r],max(g[l+1][r][k],g[l][r-1][k]));
f[l][r]=max(f[l][r],f[l][k-1]+f[k+1][r]+g[l][r][k]);
}
printf("%d\n",f[1][n]);
return 0;
}

posted on   autoint  阅读(231)  评论(0编辑  收藏  举报

编辑推荐:
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
· SQL Server统计信息更新会被阻塞或引起会话阻塞吗?
阅读排行:
· 传国玉玺易主,ai.com竟然跳转到国产AI
· 本地部署 DeepSeek:小白也能轻松搞定!
· 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)
· 我们是如何解决abp身上的几个痛点
· 普通人也能轻松掌握的20个DeepSeek高频提示词(2025版)

导航

点击右上角即可分享
微信分享提示