小红的乘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";
}