题意
给你n个木板的长度,和提高1单位长度所耗费的权值,先需要相邻的两个板子之间不能为相同高度,求最小花费
分析
如果相邻的三个木板长度为1,2,3我们发现第二个木板增长两次就可以了
如果相邻的三个木板长度为1,1,4我们发现第二个木板增长一次就可以了
如果相邻的三个木板长度为1,2,4我们发现第二个木板不需要增长
故,我们发现对于一个木板,最多增长两次
所以我们可以dp求解
设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]为第i个木板增长j次的花费
所以动态转移方程:
d
p
[
i
]
[
j
]
=
min
(
d
p
[
i
]
[
j
]
,
d
p
[
i
−
1
]
[
k
]
+
j
∗
a
[
i
]
.
s
e
c
o
n
d
)
dp[i][j]=\min(dp[i][j], dp[i-1][k]+j*a[i].second)
dp[i][j]=min(dp[i][j],dp[i−1][k]+j∗a[i].second)
最终答案为:
a
n
s
=
min
(
min
(
d
p
[
n
−
1
]
[
0
]
,
d
p
[
n
−
1
]
[
1
]
)
,
d
p
[
n
−
1
]
[
2
]
)
ans=\min(\min(dp[n-1][0], dp[n-1][1]),dp[n-1][2])
ans=min(min(dp[n−1][0],dp[n−1][1]),dp[n−1][2])
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template <typename T>
void out(T x) { cout << x << endl; }
ll fast_pow(ll a, ll b, ll p) {ll c = 1; while(b) { if(b & 1) c = c * a % p; a = a * a % p; b >>= 1;} return c;}
ll exgcd(ll a, ll b, ll &x, ll &y) { if(!b) {x = 1; y = 0; return a; } ll gcd = exgcd(b, a % b, y, x); y-= a / b * x; return gcd; }
const int N = 3e5 + 5;
const ll inf = 1e18;
typedef pair <int, int> P;
P a[N];
ll dp[N][3];
int main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while(t --)
{
int n;
cin >> n;
for(int i = 0; i < n; i ++)
{
cin >> a[i].first >> a[i].second;
dp[i][0] = dp[i][1] = dp[i][2] = inf;
}
dp[0][0] = 0;
dp[0][1] = a[0].second;
dp[0][2] = 2 * a[0].second;
for(int i = 1; i < n; i ++)
{
for(int j = 0; j < 3; j ++)
for(int k = 0; k < 3; k ++)
if(a[i].first + j != a[i - 1].first + k)
dp[i][j] = min(dp[i][j], dp[i - 1][k] + j * a[i].second);
}
cout << min(dp[n - 1][0], min(dp[n - 1][1], dp[n - 1][2])) << endl;
}
}