C. Painting Fence
题意:n列栅栏,每列有一定的高度。每次可以横着刷一行或竖着刷一列,不能跳着刷。问最少刷多少次刷完。
思路:分治。每次有两种决策,要么全部竖着刷,要么横着刷刷满最低的栅栏(因为如果不刷满,还不如竖着刷)。如果横着刷,整个栅栏可能被切为若干部分,继续对每一部分这样求解。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <map>
#include <algorithm>
using namespace std;
const int INF=1e9+10;
int a[5010];
int fun(int l,int r,int h){
if(l==r)return 1;
int re=r-l+1; //纵刷
int _min=INF;
for(int i=l;i<=r;i++){
if(a[i]<_min)_min=a[i];
}
bool flag=0;
int s=-1;
int re2=_min-h; //横刷
for(int i=l;i<=r;i++){
//cout<<i<<endl;
if(i==r){
if(flag){
if(a[i]>_min)re2+=fun(s,i,_min);
else re2+=fun(s,i-1,_min);
}else if(a[i]>_min){
re2++;
}
break;
}
if(a[i]>_min){
if(!flag){
s=i;
flag=1;
}
}else{
if(flag){
re2+=fun(s,i-1,_min);
}
flag=0;
}
}
return min(re,re2);
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int ans=fun(1,n,0);
cout<<ans<<endl;
return 0;
}