题目描述:

洛谷\(P1970\)

花匠栋栋种了一排花,每株花都有自己的高度。花儿越长越大,也越来越挤。栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致。

具体而言,栋栋的花的高度可以看成一列整数\(h_1,h_2,...,h_n\)。设当一部分花被移走后,剩下的花的高度依次为\(g_1,g_2,...,g_m\),则栋栋希望下面两个条件中至少有一个满足:

条件 \(A\):对于所有\(g_{2i}>g_{2i-1},g_{2i}>g_{2i+1}\)

条件 \(B\):对于所有\(g_{2i}<g_{2i-1},g_{2i}<g_{2i+1}\)

注意上面两个条件在\(m=1\)时同时满足,当\(m > 1\)时最多有一个能满足。

请问,栋栋最多能将多少株花留在原地。

输入输出格式:

输入格式:

第一行包含一个整数\(n\),表示开始时花的株数。

第二行包含\(n\)个整数,依次为\(h_1,h_2,...,h_n\),表示每株花的高度。

输出格式:

一个整数\(m\),表示最多能留在原地的花的株数。

输入输出样例:

输入样例:

5
5 3 2 1 2

输出样例:

3

题目分析:

​ 简单理解一下题意:

大体就是说要求留在原地的花满足:序号为\(2\)的倍数的花是左右两盆花中最高或者是最矮的

解法一:

思路:

​ 既然是\(DP\)的题,那么我们先考虑贪心(其实是为了纪念\(lz\)):

说句闲话:学习\(DP\)的最好方法是什么??

贪心!!!

好了好了,说正经的。

不过还是要吐槽这道题的算法标签,竟然没人评贪心(也不知道\(lz\)评了没有)

我们可以发现,这道题就是对一个有波动的函数进行简化,我们可以举两个例子,一个是样例:

我们可以把这个图像看做一个具有两个单调区间的函数图像,我们只能去单调区间两端的点构成新的序列,也就是说我们最多能保留三盆花

另一个是从讨论版里找来的神仙数据:

有了上面的分析,我们可以很轻易地找出\(3\)个单调区间,也就是说最多有\(4\)盆花能够被留下

算法:

​ 根据两组数据,我们可以得到这样一个算法:

扫描所有花的高度,从而得出增减区间的个数\(w\),输出\(w+1\)

代码实现:

#include<cstdio>
#include<iostream> using namespace std; inline int read()
{
int F=1,num=0;
char c=getchar();
while(!isdigit(c)){if(c=='-') F=-1; c=getchar();}
while(isdigit(c)){num=num*10+c-'0'; c=getchar();}
return num*F;
} int h[10000010];
int n;
int ans=1;//考虑到函数的左区间
int direction; int main()
{
n=read();
for(int i=1;i<=n;++i)
h[i]=read();//读入
if(h[2]>=h[1]) direction=1;//1表示增区间,0表示减区间 ,因为前两个是默认都选的,所以在这里加上了等号
for(int i=1;i<=n;++i)//我知道可以边读入边判断,但是我愿意,你管着吗??
{
if(i==n)
{
ans++;//考虑到函数的右区间,当到了右区间时答案直接加一并且跳出循环
break;
}
if(h[i+1]>h[i])
{
if(direction==0)//如果突然进入到增区间,就标记为增区间并且答案加一
{
ans++;
direction=1;
}
}
if(h[i+1]<h[i])
{
if(direction==1)//如果突然进入到减区间,就标记为减区间并且答案加一
{
ans++;
direction=0;
}
}
}
printf("%d",ans);//输出答案
return 0;
}

解法二:

思路:

​ 当然是已经哭晕在厕所的\(DP\)啦

\(dp[i][0]\)表示在\(i\)处上升时的最大盆数,\(dp[i][1]\)表示在\(i\)处下降时的最大盆数

直接得到状态转移方程

\(if(a[i]>a[i-1])\space\space\space dp[i][0]=dp[i-1][1]+1;\\if(a[i]<a[i-1])\space\space\space dp[i][1]=dp[i-1][0]+1;\\dp[i][0]=max(dp[i][0],dp[i-1][0]);\\dp[i][1]=max(dp[i][1],dp[i-1][1]);\)

解释一下:

当\(a[i]\)是上升的时候,将上升时的最大盆数更新为上一盆下降时的最大盆数+\(1\),并且用这两种状态的最大值来维护\(dp[i][0]\),表示满足条件\(B\)

当\(a[i]\)是下降的时候,将下降时的最大盆数更新为上一盆上升时的最大盆数+\(1\),并且用这两种状态的最小值来维护\(dp[i][1]\),表示满足条件\(A\)

​ 如果还不能理解就画个图,手推一下233~~

算法:

​ 就是将\(dp[1][1]\)和\(dp[1][0]\)都更新为\(1\),然后从\(2\)开始跑一遍循环,\(CV\)上面的方程就结束了

Talk is cheap,show me the code:

#include<cstdio>
#include<iostream> using namespace std; const int maxn=101000;
int dp[maxn][2],a[maxn];
int n; inline int read()
{
int F=1,num=0;
char c=getchar();
while(!isdigit(c)){if(c=='-') F=-1; c=getchar();}
while(isdigit(c)){num=num*10+c-'0'; c=getchar();}
return F*num;
} int main()
{
n=read();
dp[1][0]=1;dp[1][1]=1;
for(int i=1;i<=n;i++) a[i]=read();
for(int i=2;i<=n;i++)
{
if(a[i]>a[i-1]) dp[i][0]=dp[i-1][1]+1;
if(a[i]<a[i-1]) dp[i][1]=dp[i-1][0]+1;
dp[i][0]=max(dp[i][0],dp[i-1][0]);
dp[i][1]=max(dp[i][1],dp[i-1][1]);
}
printf("%d\n",max(dp[n][1],dp[n][0]));
return 0;
}

结语:

贪心大法真的好诶(逃

DP练习题——洛谷P1970花匠的更多相关文章

  1. 洛谷 P1970 花匠 —— DP

    题目:https://www.luogu.org/problemnew/show/P1970 普通的DP,f[i][0/1] 表示 i 处处于较小或较大的长度: 注意:1.树状数组向后 query 时 ...

  2. 洛谷P1970 花匠(dp)

    题意 题目链接 Sol 直接用\(f[i][0/1]\)表示到第\(i\)个位置,该位置是以上升结尾还是以下降结尾 转移的时候只需枚举前一个即可 #include<cstdio> #inc ...

  3. [NOIP2013] 提高组 洛谷P1970 花匠

    题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定 把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希 望剩下的花排列得比较别致. 具 ...

  4. 洛谷 P1970 花匠

    题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致. 具体而 ...

  5. 洛谷——P1970 花匠

    https://www.luogu.org/problem/show?pid=1970 题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定 把这排中的一部分花移走, ...

  6. 洛谷P1970 花匠

    传送门 首先可以知道,如果一个序列是连续上升的,那么只需要取这一个序列中最高的元素即可,因为取其它的不能保证大于后面的.连续下降的序列同理.而这些恰好就是波峰和波谷. 所以遇到 $ j $ 比之前的 ...

  7. 【线型DP】洛谷P2066 机器分配

    [线型DP]洛谷P2066 机器分配 标签(空格分隔): 线型DP [题目] 题目描述 总公司拥有高效设备M台,准备分给下属的N个分公司.各分公司若获得这些设备,可以为国家提供一定的盈利.问:如何分配 ...

  8. 洛谷P1970 [NOIP2013提高组Day2T2] 花匠

    P1970 花匠 题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定 把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希 望剩下的花排 ...

  9. Tarjan+树形DP【洛谷P2515】[HAOI2010]软件安装

    [洛谷P2515][HAOI2010]软件安装 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得 ...

随机推荐

  1. TensorFlow入门——bazel编译(带GPU)

    这一系列基本上是属于我自己进行到了那个步骤就做到那个步骤的 由于新装了GPU (GTX750ti)和CUDA9.0.CUDNN7.1版本的软件,所以希望TensorFlow能在GPU上运行,也算上补上 ...

  2. Linux查看修改文件句柄数

    SuSE 11SP3 默认句柄数是1024 1.查看linux的文件句柄数 ulimit -a 2.修改文件句柄数 ①ulimit -n 65535②修改linux系统参数.vi /etc/secur ...

  3. Linu目录结构和创建用户

    具体目标结构 ./bin [重点] (/usr/bin./usr/local/bin) ●是Binary的速写,这个目录存放着最经常使用的命令. ./sbin (/usr/sbin./usr/loca ...

  4. 【LeetCode】451-根据字符出现频率排序

    题目描述 给定一个字符串,请将字符串里的字符按照出现的频率降序排列. 示例 1: 输入: "tree" 输出: "eert" 解释: 'e'出现两次,'r'和' ...

  5. Codeforces Round #581 (Div. 2) B. Mislove Has Lost an Array (贪心)

    B. Mislove Has Lost an Array time limit per test1 second memory limit per test256 megabytes inputsta ...

  6. datax二次开发

    从hive抽取数据,写入hbase 一.datax插件hbase12xwriter开发 查看datax源码,发现有hbase094xwriter和hbase11xwriter源码,说明datax支持h ...

  7. 2019.12.9java公文流转系统

    自己来写这个系统真是没有什么思路.就弄了个登陆界面,在数据库建了个表,其它的代码一直有错误,登陆不进去.

  8. 权限和ACL练习题

    1.在/testdir/dir里创建的新文件自动属于g1组,组 g2的成员如:alice能对这些新文件有读写权限,组g3 的成员如:tom只能对新文件有读权限,其它用户(不 属于g1,g2,g3)不能 ...

  9. 数组转list

    例如String数组转成Integer泛型的List String [] pathArr = deptPath.split(","); Lit<Integer> dep ...

  10. 什么是IoC和DI?DI是如何实现的?

    IoC叫控制反转,是Inversion of Control的缩写,控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理.所谓的"控制反转" ...