CCC 2015 state1-s5 Greedy For Pies 糖果派 题解

题目

Problem Description
The local pie shop is offering a promotion - all-you-can-eat pies! Obviously, you can’t pass up this
offer.
The shop lines up N pies from left to right - the ith pie contains Ai grams of sugar. Additionally,
another M pies are provided - the ith of these contains Bi grams of sugar.
You are first allowed to insert each of the M pies from the second group anywhere into the first list of N pies, such as at its start or end, or in between any two pies already in the list. The result will
be a list of N+M pies with the constraint that the initial N pies are still in their original relative order.
Following this, you are allowed to take one walk along the new line of pies from left to right, to pick up your selection of all-you-can-eat pies! When you arrive at a pie, you may choose to add it to your pile, or skip it. However, because you’re required to keep moving, if you pick up a certain pie, you will not be able to also pick up the pie immediately after it (if any). In other words, you cannot eat consecutive pies in this combined list.
Being a pie connoisseur, your goal is to maximize the total amount of sugar in the pies you pick up from the line. How many grams can you get?
Input Specification
The first line of input contains the integer N(1N3000) . The next N lines contain one integer Ai(1Ai105) , describing the integer number of grams of sugar in pie i in the group of N pies.
The next line contains M(0M100) , the number of pies in the second list. The next M lines contain one integer Bi(1Bi105) , describing the integer number of grams of sugar in pie i in the group of M pies.
For 20% of the marks for this question, M=0. For another 20% of the marks for this question M=1 . For another 20% of the marks for this question M10 .
Output Specification
Output the maximum number of grams of sugar in all the pies that you are able to pick up.
Sample Input

5
10
12
6
14
7
11
3
1
8
2

Output for Sample Input

44

Explanation of Output for Sample Input
Place the pies in the order

10,1,12,2,8,6,14,7

(that is, insert the pie with 1 gram of sugar between 10 and 12, and insert pies with 2 and 8 grams of sugar, in that order, between pies 12 and 6). Then, we can grab 10+12+8+14=44 grams of sugar, which is maximal.

题目翻译

有两个糖果序列,分别为 aibi ,长度分别为 NM ,每个糖果都有一个美味值。现在你要将 bi 插入 ai ,使之成为一个长度为 N+M 的序列,插入规则:
你可以将每个 bi 插入 ai 的任意位置。(也就是说,bi 的原始顺序可以打乱,但是 ai 的相对顺序不变)
接下来,你要在合并好的序列中选取一些糖果,只是不能连续选取糖果,求一种合并方案,使得能够选取的糖果美味值总和最大。

题目解析

暴力方法:对于每个 bi 枚举插入点,最后做一遍DP就可以了,算法复杂度 Θ(MN(M+N)) 超时。
考虑贪心,我们发现贪心的做法显然是错误的。
我们发现题目没有要求输出路径,那么可以考虑DP。

DP式

我们发现在取糖果的时候不能连续取,那么我们将 b 数组进行升序排序,这样就可以让 b 数组的前一部分一定不取,后面的可以取也可以不取。
令函数f(i,j,k,0/1) 代表 a1i b1j,km aibk 不取/取。b 升序。
不难得到:

f(i,j,k,0)=max( f(i,j1,k,0) , f(i,j1,k,1) , f(i1,j,k,1) , f(i1,j,k,0) )

f(i,j,k,1)=max( f(i1,j,k,0)+ai , f(i,j,k+1,0)+bk )

解释:第一行第一个和第二个代表加了一个bj来垫,第三第四个代表加上了 ai 但是没有使用。
第二行第一个代表加上一个 ai ,一个加上 bk

细节

DP式搞定了,还要看一下怎么迭代。
初始值很简单,全部是 0 就可以了。
考虑循环的范围,因为要考虑到全部用来垫的情况和全部使用的情况,所以伪代码如下:

for i=1 to n
for j=0 to m+1
for k=m+1 to j

最后统计最大值即可,至于f(n,0,0,1),f(n,0,0,0)f(n,m+1,m+1,1),f(n,m+1,m+1,0)。统计不统计都无所谓,因为它们不可能是最大的,最多会和最大值相等,不会影响结果

代码

#include<cstdio>// https://www.luogu.com.cn/paste/ci11vsqa
#include<algorithm>
#define maxn 3039
#define maxm 139
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int f1[maxn],f2[maxn];
int f[maxn][maxm][maxm][2];
int a[maxn],b[maxm];
int n,m;
int main(){
//freopen("candy.in","r",stdin);
//freopen("candy.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d",&b[i]);
if(m==0){
f1[0]=f1[0]=0;
for(int i=1;i<=n;i++){
f1[i]=f2[i-1]+a[i];
f2[i]=max(f1[i-1],f2[i-1]);
}
printf("%d",max(f1[n],f2[n]));
return 0;
}
sort(b+1,b+m+1);
for(int i=1;i<=n;i++)
for(int j=0;j<=m+1;j++)
for(int k=m+1;k>=j;k--){
f[i][j][k][0]=max(f[i-1][j][k][1],f[i-1][j][k][0]);
if(j) f[i][j][k][0]=max(f[i][j][k][0],max(f[i][j-1][k][0],f[i][j-1][k][1]));
f[i][j][k][1]=max(f[i-1][j][k][0]+a[i],f[i][j][k+1][0]+b[k]);
//else f[i][j][k][1]=f[i-1][j][k][0]+a[i];
}
int maxx=-1;
for(int i=0;i<=m;i++)
maxx=max(maxx,max(f[n][i][i+1][1],f[n][i][i+1][0]));
printf("%d",maxx);
return 0;
}
posted @   jiangtaizhe001  阅读(132)  评论(1编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示