CF448C Painting Fence
题意翻译
有n块连着的木板,每个木板的高度为hih_ihi,你需要把这n块木板上色,每次 上色你可以选择竖着刷完一块木板,或者横着刷一个高度单位的连续的木板(不能中 间空着的不能跳跃),问最少需要刷几次。
题解:
联想到积木大赛。但是对于这道题来讲还有竖着刷的情况。一般思路肯定是先横着刷,刷不了了再竖着刷。但是这样的正确性难于证明。事实上,也的确是错的。因为如果出现若干小块,这么刷就不如竖着刷更划算。
那么,就按贪心的思路模拟,如果出现分块的情况,就递归下去继续模拟。
所以模拟就是递归。递归就是模拟。
那么代码就显而易见了:
#include<bits/stdc++.h>
using namespace std;
int a[5005],n;
int dfs(int l,int r)
{
if(l>r)
return 0;
if(l==r)
return min(1,a[l]);
int tot=0,last=l-1,tmp=a[l];
for(int i=l+1;i<=r;i++)
tmp=min(tmp,a[i]);
for(int i=l;i<=r;i++)
{
a[i]-=tmp;
if(!a[i])
tot+=dfs(last+1,i-1),last=i;
}
tot+=dfs(last+1,r);
return min(tot+tmp,r-l+1);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
printf("%d
",dfs(1,n));
return 0;
}