题意:
给定n座山的高度,第i座山的高度为ai。
你需要在n座山上一共造[2n]座房子,且房子只能造在高于两边山的山坡上。
你可以在一小时内减少任意山的高度。
问修建k(1≤k≤[2n])座房子的最短用时,要求输出所有情况。
题解:
dp[i][j][k]表示在区间[1,i]内建j座房子,且在第i座山建(k=1)或不建(k=0)房子的最短用时。
-
第i座山不建房子,dp[i][j][0]=min(dp[i−1][j][0],dp[i−1][j][1]+max(0,a[i]−a[i−1]+1))
-
第i座山建房子,dp[i][j][1]=min(dp[i−2][j−1][0]+max(0,a[i−1]−a[i]+1),dp[i−2][j−1][1]+max(0,a[i−1]−min(a[i−2],a[i])+1))
#include <bits\stdc++.h>
using namespace std;
const int N = 5005;
int a[N];
int dp[N][N/2][2];
int main() {
int n;
cin >> n;
for(int i = 1 ; i <= n ; i++){
cin >> a[i];
}
memset(dp, 0x3f, sizeof(dp));
dp[1][0][0] = dp[1][1][1] = 0;
for(int i = 2 ; i <= n ; i++){
dp[i][0][0] = 0;
for(int j = 1 ; j <= (i+1)/2 ; j++){
dp[i][j][0] = min(dp[i-1][j][0], dp[i-1][j][1]+max(0, a[i]-a[i-1]+1));
dp[i][j][1] = min(dp[i-2][j-1][0]+max(0, a[i-1]-a[i]+1), dp[i-2][j-1][1]+max(0, a[i-1]-min(a[i-2], a[i])+1));
}
}
for(int i = 1 ; i <= (n+1)/2 ; i++){
cout << min(dp[n][i][0], dp[n][i][1]) << ' ';
}
return 0;
}