SPOJ:House Fence(分治&DP)

"Holiday is coming, holiday is coming, hurray hurray!" shouts Joke in the last day of his college. On this holiday, Joke plans to go to his grandmother‘s house located in Schematics village. Joke‘s grandmother‘s house is more than a hundred years old. Joke is very kind hearted, so he wants to help renovate the house by painting the fence. The fence consists of N vertical boards placed on a line. The boards are numbered 1 to N from left to right, and each of them has the length of 1 meter and the height of Ai meters.

Joke‘s grandmother has a paintbrush that can be used to paint the fence. That paintbrush has a length of 1 meter. Joke paints the fence by brushing either horizontally or vertically, but the paint is expensive so Joke wants to minimize the number of paintbrush stroke. On each stroke, the paintbrush will make either a horizontal or vertical line. Also, the paintbrush must be touching the fence for the entire duration of the stroke. Joke also does not want to paint previously panted segment before. Help Joke to find the minimum number of stroke until the entire fence is covered with paint.

Input

First line contains a number N, the number of boards on the fence. The second line contains N numbers, A1, A2, A3 ... An representing the height of each board.

Output

Minimum number of stroke to paint the entire fence.

Sample Input 1

5
2 2 1 2 1

Sample Output 1

3

Sample Input 2

2
2 2

Sample Output 2

2

Sample Input 3

1
5

Sample Output 3

1

题意:又N个宽度为1的相邻围栏,每个有高度a[i],现在有一把宽度为1的刷子,可以横着刷或者竖着刷,问最少多少次刷完。

思路:对于每个区间,我们的最优情况的全部竖着刷, 或者横着刷全部公有的部分,其他的继续讨论。

由于每次最小横着刷一个,所以讨论次数不超过N。复杂度低于O(N^2)

#include<bits/stdc++.h>
using namespace std;
const int maxn=5010;
const int inf=1e9+7;
int a[maxn];
int solve(int L,int R,int H)
{
    if(L==R) return 1;
    int ht=inf,res=0,r;
    for(int i=L;i<=R;i++) ht=min(ht,a[i]);
    for(int i=L;i<=R;i++){
        if(ht==a[i]) continue;
        r=i;
        while(r<R&&a[r+1]>ht) r++;
        res+=solve(i,r,ht);
        i=r+1;
    }
    res=min(R-L+1,res+ht-H); return res;
}
int main()
{
    int N,i;
    scanf("%d",&N);
    for(i=1;i<=N;i++) scanf("%d",&a[i]);
    printf("%d\n",solve(1,N,0));
    return 0;
} 

原文地址:https://www.cnblogs.com/hua-dong/p/9090995.html

时间: 2024-10-19 00:10:30

SPOJ:House Fence(分治&DP)的相关文章

codeforces 448C C. Painting Fence(分治+dp)

题目链接: codeforces 448C 题目大意: 给出n个杆子,每个杆子有一个长度,每次可以刷一行或一列,问最少刷多少次可以将整个墙刷成黄色. 题目分析: 首先我们能够想到,如果横着刷,为了得到最优解,当前刷的位置的下面也必须横着刷,然后对于每种情况都可以通过n次竖着刷得到整个黄色的墙. 所以我们采取分治的策略进行动态规划,也就是对于每个状态划分为两种情况讨论,如果要刷横向的话,最矮要刷到最矮的柱子的高度才可能得到比竖着刷优的解,然后就变成了多个具有相同性质的规模更小的墙,然后我们可以采取

BZOJ 4518 [Sdoi2016]征途(分治DP)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4518 [题目大意] 给出一个数列,分成m段,求方差最小,答案乘上m的平方. [题解] 化简式子可以发现,就是求将数列分成m段,最小化和的平方和.设dp[i][j]表示处理到第i段,已经用了前j个数的最小代价,我们可以得到dp[i][j]=min(dp[i-1][k]+(s[j]-s[k])2),由于决策单调,可以分治DP. [代码] #include <cstdio> typede

codeforces349B - Color the Fence 贪心+DP

题意:1-9每个字母需要消耗ai升油漆,问你用油漆最多刻意画多大的数字 解题思路: 首先我们要贪心,可以知道我最优是先使我们位数尽可能长,然后才是就是位数长的情况下使得从最高位开始尽可能大.所以要取满足最长位最小的那个数,方便我们DP 解题代码: 1 // File Name: 349b.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月24日 星期四 21时40分13秒 4 5 #include<vector> 6 #include&

HDU 3507 Print Article(CDQ分治+分治DP)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3507 [题目大意] 将长度为n的数列分段,最小化每段和的平方和. [题解] 根据题目很容易得到dp[j]=min(dp[k]+(s[j]-s[k])2),因为是从前往后转移,且决策单调,因此在CDQ分治的同时进行分治DP即可. [代码] #include <cstdio> typedef long long LL; const int N=500005; int n,M,t; LL f[N],

Codeforces Round #256 (Div. 2/C)/Codeforces448C_Painting Fence(分治)

解题报告 给篱笆上色,要求步骤最少,篱笆怎么上色应该懂吧,,,刷子可以在横着和竖着刷,不能跳着刷,,, 如果是竖着刷,应当是篱笆的条数,横着刷的话,就是刷完最短木板的长度,再接着考虑没有刷的木板,,, 递归调用,,, #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define inf 999999999999999 using namespace

bzoj 3672 购票 点分治+dp

3672: [Noi2014]购票 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1177  Solved: 562[Submit][Status][Discuss] Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每个城市与它的父亲用道路连接.为了方便起见,我们将全国的 n 个城市用 1 到 n 的整数编号.

【BZOJ3769】spoj 8549 BST again DP(记忆化搜索?)

[BZOJ3769]spoj 8549 BST again Description 求有多少棵大小为n的深度为h的二叉树.(树根深度为0:左右子树有别:答案对1000000007取模) Input 第一行一个整数T,表示数据组数. 以下T行,每行2个整数n和h. Output 共T行,每行一个整数表示答案(对1000000007取模) Sample Input 2 2 1 3 2 Sample Output 2 4 HINT 对于100%的数据,1<=n<=600,0<=h<=60

SPOJ RAONE(数位dp)

RAONE - Ra-One Numbers no tags In the War between good and evil . Ra-One is on the evil side and G-One on the good side. Ra-One is fond of destroying cities and its G-one's duty to protect them.. Ra-One loves to destroy cities whose Zip Code has spec

【Foreign】动态规划 [分治][DP]

动态规划 Time Limit: 50 Sec  Memory Limit: 128 MB Description 一开始有n个数,一段区间的价值为这段区间相同的数的对数. 我们想把这n个数切成恰好k段区间.之后这n个数的价值为这k段区间的价值和. 我们想让最终这n个数的价值和尽可能少. 例如6个数1,1,2,2,3,3要切成3段,一个好方法是切成[1],[1,2],[2,3,3],这样只有第三个区间有1的价值.因此这6个数的价值为1. Input 第一行两个数n,k. 接下来一行n个数ai表示