CF1221D Make The Fence Great Again 题解

题目传送门

思路

我们发现每一个栅栏高度的增长量 \(\Delta h \in \{0, 1, 2\}\)。这是因为,每一个 \(h_i\) 都只受 \(h_{i-1}\)\(h_{i+1}\) 的约束,如果 \(\Delta h > 2\),则不会有任何的改变,故无意义。

\(dp_{i,j}\) 代表前 \(i\) 个栅栏,并且 \(\Delta h_i = j\)\(j \in \{0,1,2\}\))。很显然,直接与 \(i-1\) 的状态转移,即:

\[dp_{i,j} = \min_{0\le k\le 3,h_{i-1}+k \neq h_{i} + j}\{dp_{i-1,k}\} + j \]

转移即可。时间复杂度 \(\mathcal{O}(n)\)

代码

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

const int N = 3e5 + 5, inf = 1e18;

int t, n;
int a[N], b[N], dp[N][3];

void solve()
{
	scanf("%lld", &n);
	for (int i = 1; i <= n; i++)
		scanf("%lld%lld", &a[i], &b[i]);
	for (int i = 1; i <= n; i++)
		for (int j = 0; j < 3; j++)
			dp[i][j] = inf;
	for (int i = 0; i < 3; i++)
		dp[1][i] = i * b[1];
	for (int i = 2; i <= n; i++)
		for (int j = 0; j < 3; j++)
			for (int k = 0; k < 3; k++)
				if (a[i] + j != a[i - 1] + k)
					dp[i][j] = min(dp[i][j], dp[i - 1][k] + j * b[i]);
	int ans = inf;
	for (int i = 0; i < 3; i++)
		ans = min(ans, dp[n][i]);
	printf("%lld\n", ans);
}

signed main()
{
	scanf("%lld", &t);
	while (t--) solve();
	return 0;
}
posted @ 2025-12-20 12:30  lucasincyber  阅读(5)  评论(0)    收藏  举报