codeforces 1012C 区间DP

codeforces 1012C


题意:

n i a i 给定n座山的高度,第i座山的高度为a_i。
n [ n 2 ] 你需要在n座山上一共造[\frac n2]座房子,且房子只能造在高于两边山的山坡上。
你可以在一小时内减少任意山的高度。
k ( 1 k [ n 2 ] ) 问修建k(1≤k≤[\frac n2])座房子的最短用时,要求输出所有情况。


题解:

d p [ i ] [ j ] [ k ] [ 1 , i ] j i ( k = 1 ) ( k = 0 ) dp[i][j][k]表示在区间[1,i]内建j座房子,且在第i座山建(k=1)或不建(k=0)房子的最短用时。

  • i d p [ i ] [ j ] [ 0 ] = m i n ( d p [ i 1 ] [ j ] [ 0 ] , d p [ i 1 ] [ j ] [ 1 ] + m a x ( 0 , a [ i ] a [ i 1 ] + 1 ) ) 第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 d p [ i ] [ j ] [ 1 ] = m i n ( d p [ i 2 ] [ j 1 ] [ 0 ] + m a x ( 0 , a [ i 1 ] a [ i ] + 1 ) , d p [ i 2 ] [ j 1 ] [ 1 ] + m a x ( 0 , a [ i 1 ] m i n ( a [ i 2 ] , a [ i ] ) + 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; 
}

猜你喜欢

转载自blog.csdn.net/CSDN_PatrickStar/article/details/89739945
今日推荐