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;
}

浙公网安备 33010602011771号