zoukankan      html  css  js  c++  java
  • CF448C Painting Fence (贪心分治)

    题面

    (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
    ",fen(1,n,0));
    	return 0;
    }
    
    
  • 相关阅读:
    二分思想判断数组中是否有两数和为sum
    VC中#pragma warning指令
    (转)预编译头文件
    成为一名优秀程序员所需要知道的那些事
    SetThreadAffinityMask设置使用多核CPU的哪个核心
    DirectX 3D 设备丢失(lost device)的处理
    转载 CreateWaitableTimer和SetWaitableTimer函数
    转赵青《剑侠情缘网络版》开发回顾
    转载使用PostThreadMessage在Win32线程间传递消息
    VC使用CRT调试功能检测内存泄漏
  • 原文地址:https://www.cnblogs.com/812-xiao-wen/p/10360000.html
Copyright © 2011-2022 走看看