CF448C Painting Fence(分治递归/DFS)难度⭐⭐⭐

题目链接
有n块连着的木板,每个木板的高度为 h i h_i hi,你需要把这n块木板上色,每次 上色你可以选择竖着刷完一块木板,或者横着刷一个高度单位的连续的木板(不能中 间空着的不能跳跃),问最少需要刷几次。(注意相当于有一个宽1的刷子,每次可以刷无限长但是宽度只有1)

5
2 2 1 2 1
3
2
2 2
2

考虑横着涂一次的情况,那么有两个显而易见的事实。
这次涂色长度必须尽可能大。
在这次涂***域的下方,必定都是横着涂的。
所以,对于一串栅栏 h 1 , h 2 , , h n h_1,h_2,…,h_n h1,h2,,hn,如果要横着涂,就必定要从底向上涂 m i n ( h 1 , h 2 , , h n ) min⁡{(h_1,h_2,…,h_n)} min(h1,h2,,hn)次。这样以后, h 1 , h 2 , , h n h_1,h_2,…,h_n h1,h2,,hn就会分成若干不连通的子局面。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ifstream in("input.txt");
ofstream out("output.txt");
#define debug(x) cerr<<"# "<<x<<endl
const ll N=2e5;
const ll base=137;
const ll mod=2147483647;
const ll INF=1<<30;
ll n,m;
ll a[N],b[N];
ll DFS(ll l,ll r,ll h)
{
    if(l==r)return 1;
    if(l>r)return 0;
    ll ans=0,minn=INF,la=l-1;
    for(int i=l;i<=r;++i)
        minn=min(minn,a[i]);
    ans=minn-h;
    for(int i=l;i<=r;++i)
        if(a[i]==minn)
            ans+=DFS(la+1,i-1,minn),la=i;//表明左边已经找过了,例行地找的话从la=i开始避免重复查找
    ans+=DFS(la+1,r,minn);//例行公事
    return min(ans,r-l+1);//比较横着涂和竖着涂那个最小
}
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;++i)
        scanf("%lld",&a[i]);
    printf("%lld\n",DFS(1,n,0));
    return 0;
}

有任何疑问欢迎评论哦虽然我真的很菜

全部评论

相关推荐

不愿透露姓名的神秘牛友
昨天 14:35
点赞 评论 收藏
分享
大佬们,在大厂实习的都是几百一天???
哈尔滨的移动城堡_:那几个有名的大厂都是300-400,小厂有更高的
点赞 评论 收藏
分享
叶扰云倾:进度更新,现在阿里云面完3面了,感觉3面答得还行,基本都答上了,自己熟悉的地方也说的比较细致,但感觉面试官有点心不在焉不知道是不是不想要我了,求阿里收留,我直接秒到岗当阿里孝子,学校那边的房子都退租了,下学期都不回学校,全职猛猛实习半年。这种条件还不诱人吗难道 然后现在约到了字节的一面和淘天的复活赛,外加猿辅导。华为笔试完没动静。 美团那边之前投了个base广州的,把我流程卡麻了,应该是不怎么招人,我直接简历挂了,现在进了一个正常的后端流程,还在筛选,不知道还有没有hc。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务