线性dp——cf1012C好题

比较套路的dp题

/*
dp[i][j][0|1]:前i座山盖了j座房子,第i座不盖|盖 
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)  );
因为有冗余态,所以要初始化dp数组 
*/
#include<bits/stdc++.h>
using namespace std;

#define maxn 5005

int dp[maxn][maxn][2],n,a[maxn];

int main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    memset(dp,0x3f,sizeof dp);
    dp[0][0][0]=dp[1][1][1]=dp[1][0][0]=0; 
    a[0]=0x3f3f3f3f;
    for(int i=2;i<=n;i++){
        dp[i][0][0]=dp[i-1][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<=(1+n)/2;i++)
        cout<<min(dp[n][i][0],dp[n][i][1])<<'\n';
} 

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/10953936.html