小红的乘2除2
这题可以通过dp对所有状态进行分类讨论,比直接硬写要容易
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
#define int long long
signed main() {
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
vector<vector<int>> dp(n + 1, vector<int>(9));
// dp[0] 没有进行操作
// 最后一个数没有进行操作
// dp[1] 进行过乘操作
// dp[2] 进行过除操作
// dp[3] 进行两个操作
// 最后一个数进行操作
// dp[4] 进行乘操作 之前没有别的操作
// dp[5] 进行乘操作 之前有除法的操作
// dp[6] 进行除操作 之前没有别的操作
// dp[7] 进行除操作 之前有乘法的操作
// dp[8] 对最后一个数进行 两个操作
dp[1][1] = 1e18;
dp[1][2] = 1e18;
dp[1][3] = 1e18;
for (int i = 2; i <= n; i++)
{
int t = abs(a[i - 1] - a[i]);
dp[i][0] = dp[i - 1][0] + t;
dp[i][1] = min(dp[i - 1][1] + t, dp[i - 1][4] + abs(a[i - 1] * 2 - a[i]));
dp[i][2] = min(dp[i - 1][2] + t, dp[i - 1][6] + abs(a[i - 1] / 2 - a[i]));
dp[i][3] = min(dp[i - 1][3] + t, dp[i - 1][8] + abs(a[i] - a[i - 1] / 2 * 2));
dp[i][3] = min({ dp[i][3], dp[i - 1][5] + abs(a[i - 1] * 2 - a[i]), dp[i - 1][7] + abs(a[i - 1] / 2 - a[i])});
dp[i][4] = dp[i - 1][0] + abs(a[i - 1] - a[i] * 2);
dp[i][5] = min(dp[i - 1][2] + abs(a[i - 1] - a[i] * 2), dp[i - 1][6] + abs(a[i - 1] / 2 - a[i] * 2));
dp[i][6] = dp[i - 1][0] + abs(a[i - 1] - a[i] / 2);
dp[i][7] = min(dp[i - 1][1] + abs(a[i - 1] - a[i] / 2), dp[i - 1][4] + abs(a[i - 1] * 2 - a[i] / 2));
dp[i][8] = dp[i - 1][0] + abs(a[i - 1] - a[i] / 2 * 2);
}
cout << min({ dp[n][3], dp[n][5], dp[n][7], dp[n][8] }) << "\n";
}