线性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'; }