1. 问题描述:

给定一个长度为 n 的整数序列 a1,a2,…,an,请你从中挑选 x 个元素,要求:

  1. 原序列中的每一个长度为 k 的连续子序列都至少包含一个被选中的元素。
  2. 满足条件 1 的前提下,所选 x 个元素的相加之和应尽可能大。

输出最大可能和。

输入格式

第一行包含三个整数 n,k,x,第二行包含 n 个整数 a1,a2,…,an。

输出格式

如果无法满足题目要求,则输出 −1,否则,输出一个整数,表示所选元素的最大可能和。

数据范围

前三个测试点满足 1 ≤ k,x ≤ n ≤ 6
所有测试点满足 1 ≤ k,x ≤ n ≤ 200,1 ≤ ai ≤ 10 ^ 9

输入样例1:

5 2 3
5 1 3 10 1

输出样例1:

18

输入样例2:

6 1 5
10 30 30 70 10 10

输出样例2:

-1

输入样例3:

4 3 1
1 100 1 1

输出样例3:

100
来源:https://www.acwing.com/problem/content/description/4421/

2. 思路分析:

分析题目可以知道我们需要恰好选择 x 个元素,并且满足任意连续的 k 个元素至少包含一个选择的元素,可以发现方案数目是非常多的,Cnx 是一个指数级别的数字,所以我们需要考虑贪心或者动态规划解决,直觉上感觉可以使用 dp 来解决,由于 n 最大是 200,所以需要将时间复杂度控制到 O(n ^ 3) 以内即可,由于选择数字的时候是有顺序的所以属于序列类型的 dp(选择的时候没有顺序的属于背包类型 dp);dp 一般需要考虑两个方面:状态表示和状态计算;首先我们考虑状态表示,一般来说第一维是前 i 个数... ,后面是根据题目的限制确定有几维,一般来说有多少个限制就添加几维(限制条件),由于恰好选择 x 个数字所以选择的数字个数的限制需要一维,所以分析题目的限制可以知道我们可以定义一个二维的数组或者列表 f,其中 f(i,j) 表示所有从前 i 个数中选择 j 个数且选择了第 i 个数的所有方案的集合的最大值;因为需要保证任意连续 k 个数字中有一个数字被选择,这个条件等价于没有被选的数字的长度不超过 k - 1,所以需要保证任意两个被选择的数字之间的距离小于等于 k,所以我们需要知道哪些数字被选了;然后我们需要考虑怎么样进行状态计算,状态计算一般对应集合的划分,我们需要将当前的集合 f[i][j] 划分为若干个不同的子集,由于这道题目需要求解最大值,所以划分的子集只要不遗漏就行,划分子集一般是找最后一个不同点,由于 f[i][j] 最后一个数字是一定被选的,所以最后一个数字是固定的,所以我们看倒数第二个选择数字的位置,根据倒数第二个数字的位置 u 将 f[i][j] 划分为若干个不同的子集,由于需要满足任意连续的 k 个元素中至少需要包含一个被选的元素,所以倒数第二个位置 u 最小需要从 i - k 开始,最大为 i - 1,对于倒数第二个位置 u ,f[i][j] = max(f[i][j],f[u][j - 1] + v),其中 v 为 ai;由于需要枚举 n ^ 2 个状态(第一维枚举前 i 个数字,第二维枚举选择了 j 个数字),状态计算需要枚举选择的倒数第二个数字的位置 u,所以总的时间复杂度为 O(n ^ 3) 是可以通过的,而且可以发现每一次枚举的时候 j 固定的时候每一次对于 i 来说求解 i - k ~ i - 1 的最大值,我们可以先枚举 j ,然后使用单调队列求解一个滑动窗口的最值这样就可以将时间复杂度由 O(n ^ 3) 优化到 O(n ^ 2);还有一个问题是如何初始化呢?因为求解的是最大值所以我们不希望不合法的状态去更新答案,所以一开始的时候可以将所有状态设置为负无穷,并且考虑边界状态 f(0,0),可以发现 f(0,0) 不好解释具体的含义(强行解释从前 0 个数中选并且选择了 0 个数字的最大值为 0),我们可以不解释具体的状态表示的含义,只需要保证能够正确计算出其余的状态即可,可以发现 f(0,0) = 0 就可以正确计算其余的状态:f(1,1),f(2,1),f(3,1)... f(k,1) ,只需要保证能够正确计算其余的状态即可,如果计算答案呢?我们需要枚举一下,枚举所有可能的选择最后一个数字的状态:f(n,x),f(n - 1,x),...f(n - k + 1,x):

3. 代码如下:

python:

class Solution:def process(self):n, k, m = map(int, input().split())a = list(map(int, input().split()))INF = 10 ** 12f = [[-INF] * (m + 10) for i in range(n + 10)]# f[0][0]比较难解释具体的含义, 这里令其等于0是为了后面可以正确计算其他状态的值f[0][0] = 0for i in range(1, n + 1):for j in range(1, m + 1):for u in range(max(0, i - k), i):f[i][j] = max(f[i][j], f[u][j - 1] + a[i - 1])res = -1# 枚举前i个数字并且选择了第i个数字, 恰好选择了m个数字的方案, 在这些方案中取一个maxfor i in range(n - k + 1, n + 1):res = max(res, f[i][m])print(res)if __name__ == '__main__':Solution().process()

go:

package mainimport "fmt"func max(a, b int) int {if a > b {return a}return b
}func main() {var n, k, m, v intfmt.Scan(&n, &k, &m)// 为f分配内存空间f := make([][]int, n+10)for i := 0; i < n+10; i++ {f[i] = make([]int, m+10)}INF := 100000000000for i := 0; i < n+10; i++ {for j := 0; j < m+10; j++ {f[i][j] = -INF}}f[0][0] = 0for i := 1; i <= n; i++ {fmt.Scan(&v)for j := 1; j <= m; j++ {for u := max(0, i-k); u < i; u++ {f[i][j] = max(f[i][j], f[u][j-1]+v)}}}res := -1for i := n - k + 1; i <= n; i++ {res = max(res, f[i][m])}fmt.Println(res)
}

4418 选元素(递推)相关推荐

  1. 4418. 选元素(动态规划)

    4418. 选元素 文章目录 题面 思路 代码 单调队列优化 题面 思路 f [ i ] [ j ] {f[i][j]} f[i][j]:表示在前 i {i} i 个数中选,且包含第 i {i} i ...

  2. AcWing 4418. 选元素

    给定一个长度为 n 的整数序列 a1,a2,-,an. 请你从中挑选 x 个元素,要求: 原序列中的每一个长度为 k 的连续子序列都至少包含一个被选中的元素. 满足条件 1 的前提下,所选 x 个元素 ...

  3. AcWing 4418. 选元素(DP)

     f[i][j]表示[1,i]中选择j个,且选了第i个的所有方案的最大和 #include<bits/stdc++.h> using namespace std; int n,k,x; t ...

  4. matlab如何仿真递推型dft算法,递推dft算法

    0.7 0.8 0.9 1 0.6 0.7 0.8 0.9 1 伯格(Burg)递推算法 L-D算法缺点: 在计算相关函数估计时,对N个观测数据以 外的数据作零的假设,故谱估计误差较...... 第3 ...

  5. 第一章:递推与递归 【完结】

    目前,这一章都已经熟练掌握了. 目录 92. 递归实现指数型枚举 [板子题] 94. 递归实现排列型枚举 [板子题] 93. 递归实现组合型枚举[板子题] 717. 简单斐波那契 [简单 / 递推] ...

  6. 基本算法之递推与递归的简单应用

    递推与递归的简单应用 常见的枚举形式 实现指数型枚举 DFS (一) DFS (二) 位运算(一) 位运算(二) 实现组合型枚举 DFS + 剪枝 实现排列型枚举 DFS 费解的开关 奇怪的汉诺塔 分 ...

  7. 数塔(hdoj 2084,动态规划递推)

    在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少? 已经告诉你了,这是个DP的题目 ...

  8. 递归--递推之组合数

    排列在上一篇中已经写到,是个典型的深搜题,下面是介绍的组合数, 组合的基本定义是, 但是除了用这种传统的方法来求,可以用递归的方式或者是递推的方式来求, 说道递推,只要会递归, 就会递推了.关键的一部 ...

  9. 递归与递推类型题小结

    文章目录 1. 递归 1.1 解题思想 1.2 例题1(指数型枚举) 题意: 思路: 递归树模型: 时间复杂度: 代码实现: 1.3 例题2(排列型枚举) 题意: 思路: 递归树模型: 时间复杂度分析 ...

最新文章

  1. 张锋在美赢得“基因剪刀”专利判决!此前与诺奖得主纠纷多年
  2. [计算数学基础]矩阵微分
  3. airpods删除别人的配对_怎么不让别人连我的airpods
  4. 嵌入式根文件系统的移植和制作详解
  5. Ubuntu 下安装JDK
  6. Ubuntu 18.04 安装 CUDA
  7. 追忆童年系列:记一次寻找Flash小游戏的经历
  8. 将Ruby和Watir与NUnit集成
  9. 当我在荒废时间的时候会有多少人在拼命
  10. git里面的文件怎么删不掉_git如何删除已经提交的文件夹
  11. 不带脏字的英文骂人法
  12. jquery stop()方法的讲解使用
  13. 计算机主板别称是什么城,武汉别名江城又称什么城 武汉被誉为什么城之称
  14. 全国计算机模拟PPT考试,全国计算机等级考试模拟试题2课件.ppt
  15. JavaScript(第四天)—爱创课堂专业前端培训
  16. 记录学习Jsoup时第一次创建Maven项目时的报错(No marketplace entries found to handle maven-compiler-plugin:3.1)
  17. 360前端星计划学习-html
  18. 针对NFT的网络钓鱼
  19. 如何为几乎所有电话添加无线充电
  20. Eclipse安装、激活、配置最新版JRebel

热门文章

  1. 数据结构与算法A实验六图论---7-1 列出连通集(BFS DFS)
  2. 一份医院必备的「信息化建设项目」指南
  3. java线程池中断处理_Java线程中断机制
  4. 药瓶药片FPGA设计(已上板验证)
  5. Win10截图工具失效怎么办?这个方法帮你轻松修复
  6. 中国联通今年5G投资350亿元!附2019业绩PPT全文
  7. 前端性能优化 雅虎军规35条
  8. 大数据技术高频面试题汇总
  9. 关于数据库触发器(trigger)的简单使用操作
  10. LintCode 题解 |亚马逊、微软热门题:目的地的最短路径