zoukankan      html  css  js  c++  java
  • Codeforces 448C Painting Fence:分治

    题目链接:http://codeforces.com/problemset/problem/448/C

    题意:

      有n个木板竖着插成一排栅栏,第i块木板高度为a[i]。

      你现在要将栅栏上所有地方刷上油漆。

      每次你可以选择竖着刷或横着刷,但必须保证一次刷的地方不能间断。

      问你至少要刷几次才能刷满。

     

    题解:

      首先有一个贪心结论:

        对于当前要刷的一片区域,令minn为这片区域的最小高度。

        如果选择横着刷,则至少要将区域底部的minn层刷完。

        如图,至少要将下面两层刷完:

        

      

      然后考虑如何分治:

        对于当前的这一片区域,将最下面的minn层去掉之后,原区域就变成了若干个小区域。

        这样就转化成了若干个子问题。

        所以当前区域的最小次数 = min( 只竖着刷的次数, 先横着刷minn次 + ∑ 子区域的最小次数 )

        即:dfs(x,y) = min(y-x+1, minn + ∑ dfs(Li,Ri))

        边界条件:x == y时,最多只用竖着刷一次。

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #define MAX_N 5005
     5 #define INF 1000000000
     6 
     7 using namespace std;
     8 
     9 int n;
    10 int a[MAX_N];
    11 
    12 int dfs(int x,int y)
    13 {
    14     if(x==y) return 1;
    15     int minn=INF;
    16     for(int i=x;i<=y;i++) minn=min(minn,a[i]);
    17     for(int i=x;i<=y;i++) a[i]-=minn;
    18     int sum=0;
    19     int p=x;
    20     for(int i=x;i<=y;i++)
    21     {
    22         if(a[i] && (i==y || !a[i+1])) sum+=dfs(p,i);
    23         if(!a[i] && i<y && a[i+1]) p=i+1;
    24     }
    25     return min(sum+minn,y-x+1);
    26 }
    27 
    28 int main()
    29 {
    30     cin>>n;
    31     for(int i=1;i<=n;i++) cin>>a[i];
    32     cout<<dfs(1,n)<<endl;
    33 }
  • 相关阅读:
    堆排序(Heap Sort)
    快速排序(Quick Sort)
    希尔排序(Shell Sort)
    C和C++中的可变参数及宏的使用
    函数中的参数问题小结(&,*,传参与变参)
    C语言基础之struct
    C语言基础之指针
    从名字开始讲——C与C++的编译细节
    二维数组的动态初始化与复制
    《Java程序设计》第二次学习总结
  • 原文地址:https://www.cnblogs.com/Leohh/p/8252765.html
Copyright © 2011-2022 走看看