

#include <bits/stdc++.h>
using namespace std;
// 合并后的函数,计算收集硬币所需的最小步骤
int minSteps(const vector<int>& height, int l, int r, int h) {
// 如果左指针大于或等于右指针,说明没有硬币需要收集,返回 0
if (l >= r)
return 0;
// 找到当前区间 [l, r) 中最小高度的索引
int m = l; // 初始化 m 为 l
for (int i = l; i < r; i++) // 遍历区间 [l, r)
if (height[i] < height[m]) // 如果当前高度小于当前最小高度
m = i; // 更新最小高度的索引 m
// 计算最小步骤,选择以下三者中的最小值:
// 1. 在当前区间收集所有硬币的步骤数 (r - l)
// 2. 左侧区间 [l, m] 的最小步骤 + 右侧区间 [m + 1, r] 的最小步骤 + 收集到的最小高度 h 的差值
return min(r - l, minSteps(height, l, m, height[m]) + minSteps(height, m + 1, r, height[m]) + height[m] - h);
}
int main() {
int N = 0;
cin >> N;
vector<int> height(N);
for (int i = 0; i < N; i++) // 读取每个硬币堆的高度
{
cin >> height[i]; // 输入每个堆的高度
}
// 输出收集所有硬币所需的最小步骤,初始高度为 0
cout << minSteps(height, 0, N-1, 0) << endl;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
// 递归函数,用于计算收集硬币所需的最小步骤
int minStepsRecur(const vector<int>& height, int l, int r, int h) {
// 如果左指针大于或等于右指针,说明没有硬币需要收集,返回 0
if (l >= r)
return 0;
// 找到当前区间 [l, r) 中最小高度的索引
int m = l; // 初始化 m 为 l
for (int i = l; i < r; i++) // 遍历区间 [l, r)
if (height[i] < height[m]) // 如果当前高度小于当前最小高度
m = i; // 更新最小高度的索引 m
// 计算最小步骤,选择以下三者中的最小值:
// 1. 在当前区间收集所有硬币的步骤数 (r - l)
// 2. 左侧区间 [l, m] 的最小步骤 + 右侧区间 [m + 1, r] 的最小步骤 + 收集到的最小高度 h 的差值
return min(r - l,minStepsRecur(height, l, m, height[m]) + minStepsRecur(height, m + 1, r, height[m]) + height[m] - h);
// 递归计算左半部分的最小步骤
// 递归计算右半部分的最小步骤
// 加上当前高度与上一个高度的差值
}
// 主函数,用于调用递归函数并返回结果
int minSteps(const vector<int>& height, int N) {
// 从第 0 个索引到第 N 个索引,初始高度为 0
return minStepsRecur(height, 0, N, 0);
}
int main() {
int N = 0;
cin >> N;
vector<int> height(N);
for (int i = 0; i < N; i++) // 读取每个硬币堆的高度
{
cin >> height[i]; // 输入每个堆的高度
}
// 输出收集所有硬币所需的最小步骤,末尾无换行
cout << minSteps(height, N) << endl;
return 0;
}
/*
* 补偿步骤:height[m] - h 的主要作用
* 是补偿在递归过程中从一个高度调整到当前最小高度所需的额外步骤
* 这确保了我们在计算总步骤时不会遗漏任何必要的步骤。
*/