题意:你面前有宽度为1,高度给定的连续木板,每次可以刷一横排或一竖列,问你至少需要刷几次。

思路:先逆推,dp[i][j]表示第i列以后的木板都刷完了(不包括第i列)且前面的第j列是横着刷的(且假设它能够刷到后面的第i+1列),那么第i列之后不包括第i列最少需要的次数。所以当value[j]>=value[i]的时候第i列就不用刷了。

尽管这种做***出现一些不合法的情况,但是最后的推出的结果运用到的必然都是合法的情况。

我们再正着看。

最后的答案应该是dp[0][0],因为第0列是横着刷的就相当于没刷,第0列以后的都刷完了,就相当于刷完所有的。

它的来源是min(dp[1][0]+1,dp[1][1]+value[1]),即第一列是竖刷和第一列全为横刷的情况。剩下的依次类推。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5005;
int dp[maxn][maxn], a[maxn];
int main() {
    int n;
    cin >>n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = n; i >= 1; i--) {
        for (int j = 0; j < i; j++) {
            if (a[j] >= a[i]) {
                dp[i - 1][j] = dp[i][i];
            } else {
                dp[i - 1][j] = min(dp[i][j] + 1, dp[i][i] + a[i] - a[j]);
            }
        }
    }
    cout << dp[0][0] << endl;
    return 0;
}