CF_2153_D. Not Alone
题目链接:Problem - D - Codeforces
题目大意:
长度为 n 的 环形 数组 a ,每次操作 可以对每个元素 +1 或 -1,使得最终每个元素至少有一个相邻元素和它相等
求:最少的操作次数
DP:
我们可以把相同的相邻元素分为一块,
这样每一块的元素 >= 2,但是这样不方便计算,
对于一个大块来说,最小可以分成若干个小块,每个小块的元素个数为2~3,
分成小块后更好计算且与大块的计算方法结果相同
最后注意是环形,
由于块的长度不超过 3,我们只需要尝试三个分裂点 (1,2),(2,3) 和 (3,4)
转移方程:
dp[i] = min ( dp[i−2] + cost(a[i−1] , a[i]) , dp[i−3] + cost( a[i−2] , a[]i−1,a[i] ) )
对于 i 来说(最后两个看成一块,最后三个看成一块)
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<bitset>
#include<tuple>
#define inf 72340172838076673
#define int long long
#define endl '\n'
#define F first
#define S second
#define mst(a,x) memset(a,x,sizeof (a))
using namespace std;
typedef pair<int, int> pii;
const int N = 200086, mod = 998244353;
int n, m;
int a[N];
int f[N];
int cost(int x, int y) {
return abs(x - y);
}
int cost(int x, int y, int z) {
return max(x, max(y, z)) - min(x, min(y, z));
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int res = inf;
for (int cy = 0; cy < 3; cy++) {
f[0] = 0, f[1] = inf;
for (int i = 2; i <= n; i++) {
f[i] = f[i - 2] + cost(a[i - 1], a[i]);
if (i >= 3) f[i] = min(f[i], f[i - 3] + cost(a[i - 2], a[i - 1], a[i]));
}
res = min(res, f[n]);
for (int i = 2; i <= n; i++) swap(a[i - 1], a[i]);
}
cout << res << endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
cin >> T;
while (T--) solve();
return 0;
}

浙公网安备 33010602011771号