448C - Painting Fence(思维+分治)

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;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/115362025