Processing math: 100%

YZOJ P3754 Gab数列

YZOJ P3754 Gab数列

时间限制:2000MS      内存限制:131072KB

难度: 4.5

  • 题目描述

给定数列 a_1,a_2,\cdots,a_n,定义数列 b_1,b_2,\cdots,b_m 为 Gab数列 当且仅当它满足:

1,\forall 1\le i\le m 满足 b_i\in\mathbf{N^*}1\le b_i\le n

2,\sum_\limits{i=1}^{m}b_i\le k

\sum_\limits{i=1}^{m}a_{b_i} 的最大值。

  • 输入格式

第一行三个整数 nmk

第二行 n 个整数 a_i

  • 输出格式

输出仅一行,为最大值。

  • 样例输入

  • 样例输出

  • 样例说明

对应的 Gab数列 可以为 \{1,5,5,1,1,1\}

  • 数据范围

对于 15\% 的数据,n,m\le 8k\le 50

对于 40\% 的数据,n,m,k\le 200

对于另外 5\% 的数据,满足 m=k

对于另外 5\% 的数据,对于 1\le i\le j\le na_i\ge a_j

对于 100\% 的数据,n\le 3000k\le 8000m\le 10001\le a_i\le 10^9m\le k

 

 

 


 

 

 

想透了这个就是个背包。

f_{i,j} 为已选 i 个,容量为 j 的背包的最大价值,则 f_{i,j}=max\{f_{i-1,j-k}+a_k\}

那么这样是 O(NMK) 会 TLE ,怎么优化???

注意到其实 k 不必枚举 1 ~ j ,只需 1 ~ \frac{j}{i} 即可。

玄学理解一下,这里是dalao们的解释

 

 

 

 


 

 

燃鹅我比较菜,dalao们高端的方法我还是想得一知半解,于是这是我自己的理解。

其实可以考虑使用记搜的方法来实现这个背包。

搜索的时候计两个状态,表示当前搜索到 b 数组中的第几个数(step)和还剩下多少容量可以使用(left)。初始就是 DFS(1,K) ,转移就是 max\{DFS(step+1, left-i)+a_i\}, i=1 ~ N

搜索的时候满足 left \geq 0 。结束状态就是 step>M 。 然后再记忆化一下,复杂度就是 O(NMK) 和裸的背包相同。

考虑对这个搜索进行优化,最常见的就是调整搜索序。先搜大的肯定比先搜小的更快,又因为顺序对答案没有影响,所以从大到小搜索 b 数组中的元素,也就是满足 \forall 1 \leq i \leq j \leq N 都有 b_i \geq b_j 。 具体实现就是再计一个变量 prev 表示 b_{step-1} 选的数,那么 b_{step} 选的数一定不能比它大。

要注意的是,因为这个是完全背包问题,如果不按从小到大的顺序枚举 b_{step} 选的数的话就会造成有重复的状态。所以枚举的时候不能从 prev ~ 1 ,一定要从 1 ~ prev

这样时间复杂度(我不会证),也可以通过本题。

代码(跑得巨慢):

 

 

 

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注