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

posted @ 2023-03-20 17:10  pig_pig  阅读(30)  评论(0)    收藏  举报