题意:给定n个栅栏,每个栅栏高度为a[i],可以对栅栏进行修理并使其高度加1,修理费用为b[i],为了使相邻的栅栏高度不同,求最小修理费用
思路:设置状态dp[i][j]为第i个栅栏,修理高度为j,j可以是0,1,2(若相邻两栅栏高度差为1则最少要修2次),枚举i和j,还有i-1个栅栏的修理高度k,若修理过后相邻栅栏高度不同,则进行状态转移,求出最后一个栅栏不同修理高度中的最小修理费用即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5+10;
const int inf = 0x3f3f3f3f;
ll q, n, dp[maxn][3], a[maxn], b[maxn];
int main()
{
scanf("%d", &q);
while (q--) {
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%lld%lld", &a[i], &b[i]);
for (int i = 0; i < n; i++)
dp[i][0] = dp[i][1] = dp[i][2] = 1e20;
dp[0][0] = 0;
dp[0][1] = b[0];
dp[0][2] = 2*b[0];
for (int i = 1; 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]);
}
}
printf("%lld\n", min(dp[n-1][0], min(dp[n-1][1], dp[n-1][2])));
}
return 0;
}