【NOIP2017普及组正式赛】跳房子
来源:互联网 发布:关于大数据的新闻报道 编辑:程序博客网 时间:2024/05/18 02:32
这一题很有它的价值,我都要认真思考一番才能够想到方法。
先讲一下题目大意
题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一。跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画 n 个格子,这些格子都在同一条直线上。每个格子内有一个数字(整数),表示到达这个格子能得到的分数。玩家第一次从起点开始向右跳,跳到起点右侧的一个格子内。第二次再从当前位置继续向右跳,依此类推。规则规定:玩家每次都必须跳到当前位置右侧的一个格子内 。玩家可以在任意时刻结束游戏,获得的分数为曾经到达过的格子中的数字之和。 现在小 R 研发了一款弹跳机器人来参加这个游戏。但是这个机器人有一个非常严重的缺陷,它每次向右弹跳的距离只能为固定的 d。小 R 希望改进他的机器人,如果他花 g 个金币改进他的机器人,那么他的机器人灵活性就能增加 g,但是需要注意的是,每次弹跳的距离至少为 1。具体而言,当g < d时,他的机器人每次可以选择向右弹跳的距离为 d-g, d-g+1,d-g+2,…,d+g-2,d+g-1,d+g;否则(当g ≥ d时),他的机器人每次可以选择向右弹跳的距离为 1,2,3,…,d+g-2,d+g-1,d+g。 现在小 R 希望获得至少 k 分,请问他至少要花多少金币来改造他的机器人。
输入
第一行三个正整数 n,d,k,分别表示格子的数目,改进前机器人弹跳的固定距离,以及希望至少获得的分数。 相邻两个数之间用一个空格隔开。 接下来 n 行,每行两个正整数�� �� , �� �� ,分别表示起点到第i个格子的距离以及第i个格子的分数。 两个数之间用一个空格隔开。 保证�� �� 按递增顺序输入。
输出
共一行,一个整数,表示至少要花多少金币来改造他的机器人。若无论如何他都无法获得至少 k 分,输出-1。
样例输入
【输入样例 1】
7 4 10
2 6
5 -3
10 3
11 -3
13 1
17 6
20 2
【输入输出样例 2】
7 4 20
2 6
5 -3
10 3
11 -3
13 1
17 6
20 2
样例输出
【输出样例 1】
2
【输入输出样例 1 说明】
花费 2 个金币改进后,小 R 的机器人依次选择的向右弹跳的距离分别为2,3,5,3,4,3,先后到达的位置分别为 2,5,10,13,17,20,对应 1, 2, 3, 5, 6, 7 这 6 个格子。这些格子中的数字之和 15 即为小 R 获得的分数。
【输入输出样例 2】
-1
【输入输出样例 2 说明】
由于样例中 7 个格子组合的最大可能数字之和只有 18 ,无论如何都无法获得 20 分。
数据范围限制
本题共 10 组测试数据,每组数据 10 分。对于全部的数据满足1 ≤ n ≤ 500000,1 ≤ d ≤2000,1 ≤ xi,k≤ 10^9 , |s i | < 10^ 5 。
对于第1,2 组测试数据,n ≤ 10;
对于第3,4,5组测试数据, n ≤ 500
对于第 6,7,8 组测试数据,d = 1
这一题有一点难了,不过,这毕竟是NOIP普及组第四题嘛!
正解——二分+单调队列。
首先二分答案,然后就可以用一个单调队列来做(记得要维持好单调队列)
时间复杂度就不用说了,相信读者们都知道(此题可过)。
上一下主要代码
二分答案部分:
l:=0;//head r:=a[n,1]+d;//tail ans:=-1;//输出的最小价值 while l<=r do begin mid:=(l+r) div 2;//二分变量 if pd(max(1,d-mid),mid+d) then//pd是用来判断是否成立的,在下面的单调队列有讲 begin ans:=mid; r:=mid-1; end else l:=mid+1; end; writeln(ans);
单调队列(判断能否得到k价值)部分:
function pd(zx,zd:longint):boolean;var f,q:array[0..500000] of int64; i,j,head,tail,last:longint;begin head:=1; tail:=1; last:=-1;//用来优化时间的 q[1]:=0; f[0]:=0; for i:=1 to n do begin f[i]:=0; for j:=last+1 to i-1 do begin if (a[j,1]+zx<=a[i,1]) and (a[j,1]+zd>=a[i,1]) then//判断能否从a[j,1]跳到a[i,1] begin while (f[q[tail]]<f[j]) and (head<=tail) do dec(tail);//删尾 inc(tail); q[tail]:=j; last:=j; end; end; while ((a[q[head],1]+zd<a[i,1]) or (a[q[head],1]+zx>a[i,1])) and (head<=tail) do inc(head);//移头 if (head>tail) then f[i]:=-maxlongint else f[i]:=f[q[head]]+a[i,2];//找到从零点到a[i,1]的最大获得价值 if f[i]>=k then exit(true); end; exit(false);end;
还是上一下源代码吧!
var a:array[0..500000,1..2] of longint; n,d,k,i,l,r,ans,mid:longint;function max(x,y:longint):longint;begin if x>y then exit(x) else exit(y);end;function pd(zx,zd:longint):boolean;var f,q:array[0..500000] of int64; i,j,head,tail,last:longint;begin head:=1; tail:=1; last:=-1; q[1]:=0; f[0]:=0; for i:=1 to n do begin f[i]:=0; for j:=last+1 to i-1 do begin if (a[j,1]+zx<=a[i,1]) and (a[j,1]+zd>=a[i,1]) then begin while (f[q[tail]]<f[j]) and (head<=tail) do dec(tail); inc(tail); q[tail]:=j; last:=j; end; end; while ((a[q[head],1]+zd<a[i,1]) or (a[q[head],1]+zx>a[i,1])) and (head<=tail) do inc(head); if (head>tail) then f[i]:=-maxlongint else f[i]:=f[q[head]]+a[i,2]; if f[i]>=k then exit(true); end; exit(false);end;begin assign(input,'jump.in');reset(input); assign(output,'jump.out');rewrite(output); readln(n,d,k); for i:=1 to n do read(a[i,1],a[i,2]); l:=0; r:=a[n,1]+d; ans:=-1; while l<=r do begin mid:=(l+r) div 2; if pd(max(1,d-mid),mid+d) then begin ans:=mid; r:=mid-1; end else l:=mid+1; end; writeln(ans); close(input); close(output);end.
这些地方都很容易理解,就是如何实现,因为那些细节真的是太多了!
(今年NOIP普及组没能AK,真的是不幸中的不幸)
- 【NOIP2017普及组正式赛】跳房子
- [NOIP2017普及组]跳房子
- NOIP2017普及组★跳房子
- 【NOIP2017普及组正式赛】成绩
- 【NOIP2017普及组正式赛】 图书管理员
- 【NOIP2017普及组正式赛】棋盘
- NOIP2017跳房子(普及T4)
- 【NOIP2017普及组T4】跳房子-二分答案+DP单调队列优化
- 【NOIP2017】跳房子
- NOIP 2017 普及组 跳房子 jump
- NOIP2016普及组正式赛
- NOIP2017普及组题解
- NOIP2017普及组
- [NOIP2017普及组]棋盘
- 【NOIP2017普及组】棋盘
- NOIP2017普及组题解
- NOIP2017普及组总结
- [NOIP2017普及组]成绩
- Linux下vim的常用命令
- first_report_gu
- C++ 继承、虚继承、虚函数类内存分配
- tomcat+myeclipse+mysql环境搭建
- 深入理解数据结构之链表
- 【NOIP2017普及组正式赛】跳房子
- 初识Hibernate(一)之配置文件以及框架搭建
- CSS background背景知识详解
- 【spring框架】spring获取webapplicationcontext,applicationcontext几种方法详解
- c++学习笔记第一篇 列车调度问题
- 制作游戏2
- CHROME开发者工具的小技巧
- 个人编写的一个JS表单验证插件
- EventBus 笔记