E.Easy Climb

Somewhere in the neighborhood we have a very nice mountain that gives a splendid view over the surrounding area. There is one problem though: climbing this mountain is very difficult, because of rather large height differences. To make more people able to climb the mountain and enjoy the view, we would like to make the climb easier.

To do so, we will model the mountain as follows: the mountain consists of n adjacent stacks of stones, and each of the stacks is hi high. The successive height differences are therefore hi+1-hi (for 1 ≤ i ≤ n-1). We would like all absolute values of these height differences to be smaller than or equal to some number d.

We can do this by increasing or decreasing the height of some of the stacks. The first stack (the starting point) and the last stack (the ending point) should remain at the same height as they are initially. Since adding and removing stones requires a lot of effort, we would like to minimize the total number of added stones plus the total number of removed stones. What is this minimum number?

Input

On the first line one positive number: the number of testcases, at most 100. After that per testcase:
One line with two integers n (2 ≤ n ≤ 100) and d (0 ≤ d ≤ 109): the number of stacks of stones and the maximum allowed height difference.
One line with n integers hi (0 ≤ hi ≤ 109): the heights of the stacks.
Output

Per testcase:
One line with the minimum number of stones that have to be added or removed or “impossible” if it is impossible to achieve the goal.
Sample Input

3
10 2
4 5 10 6 6 9 4 7 9 8
3 1
6 4 0
4 2
3 0 6 3
Sample Output

6
impossible
4

The 2008 ACM Northwestern European Programming Contest

题意:给了n个堆的高度,要求改变堆的高度,首尾不可改变,使得队列的任意相邻的两数之差<=d,求最小代价

题解:

首先,如果数据范围很小的话 可以直接定义dp[i][j]表示处理完前i个高度后最后一个高度为b[j]的最小花费。 这样定义状态正确性是显而易见的。

然而 这里的d范围是10^9 显然不允许我们这么暴力的去枚举每一个状态。
所以需要去剪枝。 观察到最多只有100个高度, 却分布在1e9的范围里
肯定有很多状态是不会被用到的,应该要想到用离散化缩小范围。

首先,考虑只有3个值的情况:h1, h2, h3。那么根据题意,h2的范围应该在区间[h1-d,h1+d]和[h3-d,h3+d]的交集,即h1应该在[max(h1,h3)-d,min(h1,h3)+d]之间。如果这个区间是空集,即abs(h3-h1)>(3-1)*d,那么自然无解,否则:

1、如果h2就在区间内部,那么不需要修改;

2、如果h2<max(h1,h3)-d,那么就修改为交集的区间下界max(h1,h3)-d;

3、如果h2>min(h1,h3)+d,那么就修改为交集区间的上界min(h1,h3)+d。

可以发现,在这个简单的问题中,h2的最优修改方案只有这3种情况。并且我们还发现了,如果要修改,修改后的高度一定是如hp+k*d的形式。---离散化缩小范围

离散化缩小范围后呢,

下面需要想的就是状态转移方程了。

dp[i][j]=min(dp[i-1][k])+abs(x[j]-h[i]);// j-d<=k<=j+d;

一般单调队列有头,尾两个指针来维持单调性,这里只用一个头指针就完成普通单调队列的写法,在本题中 直接把b[] 数组当单调队列来用了
首先

具体做法是:

1.先维护窗口左边界,别让指针k超出了窗口,如果bk] < b[j] - d那么就k++ (因为b数组是从小到大已经排好序的),然后在不超出右边界b[j]+d 的前提下,如果dp[i][k+1] <= dp[i][k],那么k++;

为什么这样是对的的? 好像和之前说的优先队列一点也不一样啊! 其实是一样的操作,仔细回想维护优先队列时是怎么操作的 :用两个指针front、rear 先更新左边界,防止当前位置超出区间边界,一旦超出就front++; 然后每次新加进来一个值就要看看当前队列最右端的元素与新值的大小,如果大于新值那么就rear--,将无用的元素请出队列 ,直到小于新值,就将新值加入, 然而其实上边那个用一个指针的方法是如出一辙的,只不过将删除无用值这一步放到了求最小值时,也就是更新k时

         

#include<iostream>
#include<algorithm>
#include<math.h>
#define ll long long
#define mx 999999999999
using namespace std;
ll a[],b[],dp[][];// dp[i][j]表示 处理完前i座山后 最后一座山的高度为b[j]的最小花费;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,d;
cin>>n>>d;
for(int i=;i<n;i++)
cin>>a[i];
if(abs(a[n-]-a[])>(n-)*d)
{
cout<<"impossible"<<endl;
continue;
}
ll cnt=;
for(int i=;i<n;i++)//离散化,处理后将山所有可能的改变值存在b数组
{
for(int j=;j<n;j++)
{
b[cnt++]=a[i]+j*d;
b[cnt++]=a[i]-j*d;
}
}
int m;
sort(b,b+cnt);
m=unique(b,b+cnt)-b;
for(int i=;i<m;i++)//初始化dp
{
dp[][i]=mx;
if(b[i]==a[])
dp[][i]=;
}
for(int i=;i<n;i++)
{
int k=;//单调队列头指针
for(int j=;j<m;j++)//如果山峰的高度要改变为b[k],那么b[k]的范围为[b[j]-d,b[j]+d],并且要达到最优,要么改变为b[k]-d,要么改变为b[k]+d
{
while(k<m&&b[k]<b[j]-d)//改变为区间下界值b[j]-d;找到b[k]>=b[j]-d就退出
k++;
while(k+<m&&b[k+]<=b[j]+d&&dp[i-][k+]<=dp[i-][k])//改变为区间上界值b[j]+d
k++;
if(dp[i-][k]==mx)
dp[i][j]=mx;
else
dp[i][j]=dp[i-][k]+abs(b[j]-a[i]);
}
}
for(int i=;i<m;i++)
{
if(b[i]==a[n-])
cout<<dp[n-][i]<<endl;
}
}
}

         

Easy Climb UVA - 12170 滚动dp +离散化+ 单调队列优化的更多相关文章

  1. 洛谷P3975 跳房子 [DP,单调队列优化,二分答案]

    题目传送门 跳房子 题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一. 跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画 n 个格子,这些格子都在同一 ...

  2. Codeforces 487B Strip (ST表+线段树维护DP 或 单调队列优化DP)

    题目链接 Strip 题意   把一个数列分成连续的$k$段,要求满足每一段内的元素最大值和最小值的差值不超过$s$, 同时每一段内的元素个数要大于等于$l$, 求$k$的最小值. 考虑$DP$ 设$ ...

  3. HDU 4374 One hundred layer DP的单调队列优化

    One hundred layer Problem Description   Now there is a game called the new man down 100th floor. The ...

  4. P2034 选择数字——线性dp(单调队列优化)

    选择数字 题目描述 给定一行 \(n\) 个非负整数 \(a[1]...a[n]\) .现在你可以选择其中若干个数,但不能有超过 \(k\) 个连续的数字被选择.你的任务是使得选出的数字的和最大. 输 ...

  5. ZOJ2067 经典 DP(单调队列优化)

    题目:一个由‘.’和‘#’组成矩形,统计里面'.'组成的矩形的个数. 点击打开链接 自己写挂了,懒得搞了 #include <stdio.h> #include <string.h& ...

  6. [小明打联盟][斜率/单调队列 优化dp][背包]

    链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...

  7. [BZOJ1044][HAOI2008]木棍分割 二分 + 单调队列优化dp + 滚动数组优化dp

    Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长 ...

  8. 2018.09.10 bzoj1499: [NOI2005]瑰丽华尔兹(单调队列优化dp)

    传送门 单调队列优化dp好题. 这题其实很简单. 我们很容易想到一个O(T∗n∗m)" role="presentation" style="position: ...

  9. bzoj 1499 [NOI2005]瑰丽华尔兹——单调队列优化dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1499 简单的单调队列优化dp.(然而当时却WA得不行.今天总算填了坑) 注意滚动数组赋初值应 ...

随机推荐

  1. 【转载】手把手教你使用Git(简单,实用)

    手把手教你使用Git(简单,实用) 标签: git 2016年04月21日 20:51:45 1328人阅读 评论(0) 收藏 举报 一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. ...

  2. 第4节 Scala中的actor介绍:1、actor概念介绍;2、actor执行顺序和发送消息的方式

    10.    Scala Actor并发编程 10.1.   课程目标 10.1.1.    目标一:熟悉Scala Actor并发编程 10.1.2.    目标二:为学习Akka做准备 注:Sca ...

  3. Android游戏开发学习(5)--实现Button悬浮于与SurfaceView之上

    原文:http://daikainan.iteye.com/blog/1407355 实现Button悬浮于与SurfaceView之上实现 先看效果: 注意:你实现的SurfaceView和andr ...

  4. 企业面试问题收集-ssh框架

    SSH框架阶段 SSH的优缺点,使用场景? Hibernate优缺点 Hibernate优点:(1) 对象/关系数据库映射(ORM)它使用时只需要操纵对象,使开发更对象化,抛弃了数据库中心的思想,完全 ...

  5. 收藏 40 2 CPD (广告合作方式)

    CPD,Cost per day的缩写,意思是按天收费,是一种广告合作方式. 在实际的广告合作中根据行业不同还包括Cost per Download的缩写含义,意思是依据实际下载量收费.   “CPD ...

  6. 记录一次Nginx使用第三方模块fair导致的线上故障排错

    一.问题 今天发现有一台服务器的内存飙升,然后有预警,立即排查,发现该服务内存使用达到了 2G ,询问开发,当天是否有活动,被告知没有,登陆 Pinpoint 发现该服务是有两台机器,并且所有的访问都 ...

  7. Firefox 的 hack 及 问题

    hack: @-moz-document url-prefix(){ #selector{ display: flex; justify-content: space-between; } } 问题一 ...

  8. Centos7 配置subversion

    CentOS7:配置SVN服务器 Posted on 2016-11-10 15:17 eastson 阅读(4266) 评论(0) 编辑 收藏 1. 安装 CentOS通过yum安装subversi ...

  9. Spring--@configuration 和 @Bean

    参考:http://wiki.jikexueyuan.com/project/spring/java-based-configuration.html @Configuration 和 @Bean 注 ...

  10. P1250 种树 题解

    题目描述 一条街道的一边有几座房子,因为环保原因居民想要在路边种些树,路边的居民被分割成 n 块,并被编号为 1…n.每块大小为一个单位尺寸并最多可种一棵树.每个居民想在门前种些树并指定了三个数b,e ...