题目:https://ac.nowcoder.com/acm/contest/62642/B
妈妈成功将小竹救了出来,她觉得小竹实在是太笨了,决定关小竹一周禁闭。可是小竹哪里能忍受失去自由,他早就偷藏了一部手机用于联系你,请求你帮助他逃离。
你通过观察发现他房间内有 n 个可用于制成绳子的物品,第 i 个的长度为 ai 。当你使用第 i个物品制作绳子时,其右侧的 k 个物品(不含第 i 个物品)就无法再被用于制作绳子 。最终,小竹用选择的物品制成绳子,绳子的长度是所选择物品的长度之和。
小竹想知道,他能制作的绳子长度最长为多少?
输入描述:
第一行两个整数 n,k(1≤k≤n≤2000) 第二行n个用空格隔开的整数,第i个整数为 ai(1≤ai≤2000)表示第i个物品的长度。
输出描述:
一行一个整数,表示绳子的最长长度。
示例1
输入
1 2 3 4 5
输出
7
说明
使用第2个和第5个物品制成绳子
总结:
经典的dp思维:状态转移方程 -- 该题两种状态的储存
第1种就是新位置的储存
第2中就是老位置的储存
具体代码:
dp[a] = max( dp[y]+q[a], dp[a-1] ); //选择最大长度进行储存
代码献上(dp):
#include<bits/stdc++.h>
using namespace std;
int n, k;
const int N = 2023;
int q[N];
int dp[N]; //数组的每一个位置表示从头到该位置最大长度
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> k;
for (int a = 1; a <= n; a++)cin >> q[a]; //数据输入
for (int a = 1; a <= n; a++)
{
int y = max(0, a - k - 1); //跳过k个物品
dp[a] = max( dp[y]+q[a], dp[a-1] ); //选择最大长度进行储存
//dp[a-1] 表示上一个储存最大的
//dp[y]+q[a] 表示该位置的长度与前第k个物品
}
cout << dp[n];
return 0;
}