码迷,mamicode.com
首页 > 其他好文 > 详细

CF448C Painting Fence (贪心分治)

时间:2019-02-10 20:44:44      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:bre   ret   string   paint   结合   algorithm   http   int   mat   

题面

技术图片

技术图片

\(solution:\)

一道蛮水的分治题,但思想很不错(虽然我还是非常天真的以为是积木大赛原题,并且居然还有30分)

看到这个题目,根据贪心的一贯风格,我们肯定能想到将整个栅栏的下面某部分直接用几次横向的操作把它涂掉。然后我们发现如果将涂了色的部分不管,整段栅栏会被我们分成若干个部分(最短的竖条栅栏因为贪心会被横着涂完,然后整个栅栏会被分为左(中)右几个部分)。然后我们将这几个依次用这种办法分治。再然后我们发现我们好像把纵向操作忘记了,它在什么地方用呢?我们在每一次求某段栅栏最小次数时比较一下:将它全部纵向涂色用的步数少还是横纵结合的步数少(这段栅栏被分治时某一部分被全部用了纵向操作)。

然后我们的边界条件就是当某一段栅栏被分得只有一条的时候,直接纵向刷一次即可!

\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int

using namespace std;

int n;
int a[5005];

inline int qr(){
    char ch;
    while((ch=getchar())<'0'||ch>'9');
    int res=ch^48;
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+(ch^48);
    return res;
}

inline int fen(int l,int r,int h){
    if(l>r)return 0;//特判
    if(l==r)return 1;//边界
    int tot=0,mi=inf;
    for(rg i=l;i<=r;++i)
        mi=min(mi,a[i]);//贪心的找能横向涂多少次
    for(rg i=l,j;i<=r;i=j+1){
        for(j=i;j<=r;++j)
            if(a[j]==mi)break;
        tot+=fen(i,j-1,mi);
    }return min(r-l+1,tot+(mi-h));//横纵比较
}

int main(){
    freopen("color.in","r",stdin);
    freopen("color.out","w",stdout);
    n=qr();
    for(rg i=1;i<=n;++i)a[i]=qr();
    printf("%d\n",fen(1,n,0));
    return 0;
}

CF448C Painting Fence (贪心分治)

标签:bre   ret   string   paint   结合   algorithm   http   int   mat   

原文地址:https://www.cnblogs.com/812-xiao-wen/p/10360000.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!