P7381 [COCI2018-2019#6] Sličice
[COCI2018-2019#6] Sličice
题目描述
Nikola 喜欢收集足球队员的照片,并将其保存在相册中。他计划收集 \(N\) 支球队的队员照片,其中每支球队都有 \(M\) 张。
对于 Nikola 所收集的每支球队,该球队的照片数量 \(x\) 能给他增加分数 \(B_x\)。他目前拥有球队 \(i\) 的照片数量为 \(P_i\)。
Nikola 的好朋友 Ivan 有两套完整的相册。Ivan 决定送 \(K\) 张照片给 Nikola。Nikola 想要知道,在得到这 \(K\) 张照片之后,它的相册所能得到的分数的最大值。
输入格式
第一行输入整数 \(N,M,K\)。
第二行输入 \(N\) 个整数 \(P_i\)。
第三行输入 \(M+1\) 个整数 \(B_i\),其中 \(B_i\) 表示一支球队收集到了 \(i\) 张不同的照片能够获得 \(B_i\) 分。
对于 \([0,M-1]\) 内的每一个整数 \(t\),都满足 \(B_t \le B_{t+1}\)。同时 \(K \le N \times M-\sum_{i=1}^N P_i\)。
输出格式
输出能够得到的分数的最大值。
样例 #1
样例输入 #1
4 4 3
4 2 3 1
0 1 3 6 10
样例输出 #1
31
样例 #2
样例输入 #2
4 3 5
1 1 2 3
0 1 2 3
样例输出 #2
12
样例 #3
样例输入 #3
3 6 2
2 4 1
31 38 48 60 75 91 120
样例输出 #3
206
提示
样例 1 解释
Nikola 一开始拥有球队 \(1,2,3,4\) 照片数量分别为 \(4,2,3,1\)。最优的方案是获得球队 \(2,3\) 照片各 \(1\) 张。此时分数最大,为 \(10+10+10+1=31\)。
数据规模与约定
对于 \(20\%\) 的数据,\(K=2\)。
对于 \(100\%\) 的数据,\(1 \le N,M \le 500\),\(1 \le K \le \min(N \times M,500)\),\(0 \le P_i \le M\),\(0 \le B_i \le 10^5\)。
说明
题目译自 COCI2018-2019 CONTEST #6 T3 Sličice。
题目解读
对于n只球队,第i只队有初始照片数p[i],现有k张多余照片可以加在任意球队上。对于每只球队的照片数t,有b[t]代表其价值。求价值最大值。
问题解决
观察题目,发现可以类比为有初始状态的背包问题,设计f[i][j]来表示选择至i只球队时,分配j张照片所能达到的最大价值。
因此,若用i表示当前球队,j表示总计可分配照片数,z表示在当前球队上分配的照片数。
则有f[i][j]=max(f[i-1][j-z]+b[p[i]+z].
其中[i-1]表示过去状态,[j-z]代表为将要分配的照片所留出的空间,而b[p[i]+z]则是分配后增加的价值.
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define N 505
int n,m,k;
int p[N],b[N];
int f[N][N];
inline int read()
{
int x=0;
bool f=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar())
if(ch=='-')
f=0;
for(;isdigit(ch);ch=getchar())
x=(x<<1)+(x<<3)+ch-'0';
return f?x:(~(x-1));
}
int main()
{
n=read();m=read();k=read();
for(int i=1;i<=n;i++)p[i]=read();
for(int i=0;i<=m;i++)b[i]=read();
for(int i=1;i<=n;i++)
for(int j=0;j<=k;j++)
for(int z=0;z<=j;z++)
f[i][j]=max(f[i][j],f[i-1][j-z]+b[p[i]+z]);
cout<<f[n][k];
return 0;
}
本文来自博客园,作者:pig_pig,转载请注明原文链接:https://www.cnblogs.com/pigAlg/p/17237006.html
浙公网安备 33010602011771号