思路:
s:起点 t:终点 l:左端点 r:右端点
以上称为关键点
dp[i][j]表示到位置 i 为止,已经经过前 j 个关键点的最小花费
转移方程看代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << " "; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 2e5 + 10; LL dp[N][5]; int a[N]; int main() { int n; scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int i = 1; i <= n; i++) { dp[i][0] = dp[i-1][0] + a[i]; for (int j = 1; j < 5; j++) { dp[i][j] = dp[i-1][j]; for (int k = 0; k < j; k++) dp[i][j] = min(dp[i][j], dp[i-1][k]); } dp[i][1] += a[i] == 0 ? 2 : (a[i]%2 != 0); dp[i][2] += a[i]%2 != 1; dp[i][3] += a[i] == 0 ? 2 : (a[i]%2 != 0); dp[i][4] += a[i]; } LL ans = dp[n][0]; for (int i = 1; i < 5; i++) ans = min(ans, dp[n][i]); printf("%lld ", ans); return 0; }