https://codeforces.com/problemset/problem/448/C
思路:
对于一段区间,一个上界代价就是其长度。然后就是横涂到最小的高度就产生了分段。对于这些分段采取同样的方法进行处理。也就是说,对于这个区间,我最后是竖着全部涂完,还是横着配合怎么样,我dfs进入更小的区间得到最优解再返回回来,根据该返回结果的汇总取一个最小再返回去。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=5e3+100;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL a[maxn];
LL dfs(LL l,LL r){
LL sum=r-l+1;
if(r-l+1<=2){
return min(sum,max(a[l],a[r]));
}
LL minv=0x3f3f3f3f;
for(LL i=l;i<=r;i++){
minv=min(minv,a[i]);
}
for(LL i=l;i<=r;i++) a[i]-=minv;
LL res=minv;
LL sl=0;LL sr=0;
for(LL i=l;i<=r;i++){
if(a[i]>0&&sl==0) sl=i;
if(a[i]!=0&&a[i+1]==0&&sr==0) sr=i;
if(sr>=sl&&sr&&sl){
res+=dfs(sl,sr);///返回该区间的最小处理代价
sl=0;sr=0;
}
}
sum=min(sum,res);
return sum;
}
int main(void){
LL n;n=read();
for(LL i=1;i<=n;i++) a[i]=read();
LL temp=dfs(1,n);
printf("%lld\n",temp);
return 0;
}