[NOIP 2024 模拟3]变幻

[NOIP 2024 模拟3]变幻

题意

给出长度为 n 的序列 a。可以进行 k 次修改。

每次修改可以把一个数变得更小。求序列中山谷数之和的最大值。

思路

动态规划,定义 dpi,j 表示前 i 个数进行 j 次修改的最大和。

因为连续两个点只可能有一个成为山谷数,所以 ii2 转移得到。

转移方程:

  1. 继承 dpi,j=dpi1,j
  2. 当前数为山谷数 dpi,j=dpi2,j
  3. 当前数不为山谷数 dpi,j=dpi2,j1+min{ai1,ai+1}1

i=2 转移到 i=n1,因为 i=1i=n 没用。

答案为 mini=1jdpn1,i

代码

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
const int N = 2e3 + 5;

int n, k, a[N];
ll dp[N][N], ans;

bool yes(int x) {
	if (x == 1 || x == n) {
		return 0;
	}
	return a[x] < a[x + 1] && a[x] < a[x - 1];
}

int main() {
	freopen("A.in", "r", stdin);
	freopen("A.out", "w", stdout);
	cin >> n >> k;
	for (int i = 1; i <= n; i ++) {
		cin >> a[i];
	}
	for (int i = 2; i < n; i ++) {
		for (int j = 0; j <= k; j ++) {
			dp[i][j] = dp[i - 1][j];
			if (yes(i)) {
				dp[i][j] = max(dp[i][j], dp[i - 2][j] + a[i]);
			}
			if (j) {
				dp[i][j] = max(dp[i][j], dp[i - 2][j - 1] + min({a[i - 1], a[i + 1], a[i]}) - 1);
			}
		}
	}
	for (int i = 0; i <= k; i ++) {
		ans = max(ans, dp[n - 1][i]);
	}
	cout << ans << "\n";
	return 0;
}
posted @   maniubi  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示