题意:有n座山,你要在山上建房子,建房子的山需要满足的条件是两边山的高度要严格小于它,你可以降低一些山的高度,每减少一个单位的高度,需要消耗一个单位的时间,求建1、2...、(n+1)/2座山分别需要的耗费的最小时间。
dp1[i][j]: 到i上建了j个最少cost(i上有房,此时不考虑后一个大小)
dp2[i][j]: 到i上建了j个最少cost(i上不一定有,考虑后一个大小,相当于一个前缀最优的思想)
后期滚动数组优化一下
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
using namespace std;
int n;
int a[5005];
long long dp1[5][2505];
long long dp2[5][2505];
long long inf=1e18+7;
int main() {
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
a[0]=1e9+7;
a[n+1]=0;
for(int i=0;i<5;i++)
{
for(int j=0;j<=2503;j++)
dp1[i][j]=dp2[i][j]=inf;
}
dp1[0][0]=0;
dp2[0][0]=0;
dp1[1][0]=dp1[1][1]=0;
dp2[1][0]=0; dp2[1][1]=max(0,a[2]-a[1]+1);
int len=n/2;
if(n%2==1)
len++;
int cur=1;
for(int i=2;i<=n;i++)
{
cur=(cur+1)%5;
dp2[cur][0]=0;
int len1=i/2;
if(i%2==1)
len1++;
for(int j=1;j<=len;j++)
{
dp1[cur][j]=inf;
long long cost=max(0,a[i-1]-min(a[i-2],a[i])+1);
dp1[cur][j]=min(dp1[cur][j],dp1[(cur-2+5)%5][j-1]+cost);
//cout<<cost<<endl;
if(i>=3){
cost=max(0,a[i-1]-a[i]+1);
dp1[cur][j]=min(dp1[cur][j],dp2[(cur-3+5)%5][j-1]+cost);
}
cost=max(0,a[i+1]-a[i]+1);
dp2[cur][j]=min(dp2[(cur-1+5)%5][j],dp1[cur][j]+cost);
}
}
for(int i=1;i<=len;i++)
{
printf("%d ",dp2[cur][i]);
}
printf("\n");
}
return 0;
}