ACM: Racing Gems - 最长递增序列

Racing Gems

 

You are playing a racing game.  Your character starts at the x axis (y = 0) and proceeds up the      race track, which has a boundary at the line x = 0 and another at x = w.  You  may start the race       at any horizontal position you want, as long as it is within the track boundary.  The finish line is       at y = h, and the game ends when you reach that line.  You proceed at a fixed vertical velocity v,   but you can control your horizontal velocity to be any value between v/r and v/r, and change it     at any time.

There are n gems at specific points on the race track.  Your  job is to collect as many gems as  possible.  How many gems can you collect?

Input

The first line of input contains four space-separated integers n, r, w, and h (1 n 105, 1 r 10,  1 w, h 109). Each of the following  n lines  contains  two  space-separated  integers  xand  yi, denoting the coordinate of the ith gem (0 xi w, 0 < yi h).  There will be at most one gem        per location.

The input does not include a value for    v.

Output

Print, on a single line, the maximum number of gems that can be collected during the  race.


Sample Input


Sample Output

3


5  1  10 10


8 8


5 1


4 6


4 7


7 9


Sample Input


Sample Output

3


5  1  100 100


27 75


79 77


40 93


62 41


52 45


Sample Input


Sample Output

4


10  3  30 30


14 9


2 20


3 23


15 19


13 5


17 24


6 16


21 5


14 10


3 6

/*/
题意,跑跑车游戏,x方向速度为1,y方向自己控制范围在-1/r到1/r之间。

给出金币的坐标,最多问能捡到多少金币。

首先可以知道,我们的可以走的范围为由出发点引出的左右两条射线之内,如果下一个点在现在的点的射线范围内,那么这个金币可以被捡到。

如果没有在射线范围内,就无法被捡到

上图

可以从图中看到下面第一个绿色的点A可以直接走到的点有两个 B 和C,但是B只能再走向E,而C可以走到D,再从D走到E;

明显A-C-D-E这种路径长些,想到这里,我们可以这样去解决这个问题:

把每个点的坐标按照左右位移的速度 1/r 映射到左右两个边界,按照左右两个边界升序排序【左边界优先】,取右边界最大上升子序列就行了。

这里用到了一个迭代器upper_bound(a,a+n,x),它的作用是返回a数组中从x开始的递增序列的最后一个的地址。

AC代码:
/*/
#include"algorithm"
#include"iostream"
#include"cstring"
#include"cstdlib"
#include"cstdio"
#include"string"
#include"vector"
#include"queue"
#include"cmath"
using namespace std;
typedef long long LL ;
#define memset(x,y) memset(x,y,sizeof(x))
#define memcpy(x,y) memcpy(x,y,sizeof(x))
#define FK(x) cout<<"["<<x<<"]\n"
#define bigfor(x) for(LL qq=1;qq<= T ;qq++)

const LL MX=1e5+5;

struct Node {
	LL x,y;
	bool operator<(const Node &A)const {
		return x < A.x;
	}
	void add(LL r,LL w,LL xx,LL yy) {
		x=xx*r+yy;
		y=(w-xx)*r+yy;
	}
} nd[MX];

LL dp[MX];

int main() {
	LL n,r,w,h,x,y;
	while(~scanf("%I64d%I64d%I64d%I64d",&n,&r,&w,&h)) {
		for(LL i=1; i<=n; i++) {
			scanf("%I64d%I64d",&x,&y);
			nd[i].add(r,w,x,y);
		}
		LL ans=0;
		memset(dp,0x3f);
		sort(nd+1,nd+1+n);
		for(LL i=1; i<=n; i++) {
			LL tem=upper_bound(dp+1,dp+1+n,nd[i].y)-&dp[0];  //★
			ans = max(ans,tem);
			dp[tem]=nd[i].y;
		}
		printf("%I64d",ans);
	}
	return 0;
}

/*/
★升序排列的容器:
iterator lower_bound( const key_type &key ): 返回一个迭代器[地址],指向键值>= key的第一个元素。
iterator upper_bound( const key_type &key ):返回一个迭代器[地址],指向键值<=key的最后一个元素的后一个元素。
★降序排列的容器:
iterator lower_bound( const key_type &key ): 返回一个迭代器[地址],指向键值<= key的第一个元素。
iterator upper_bound( const key_type &key ):返回一个迭代器[地址],指向键值>=key的最后一个元素的后一个元素。
/*/

  

 
时间: 2024-11-06 00:55:40

ACM: Racing Gems - 最长递增序列的相关文章

zoj1986 Bridging Signals (dp,最长递增序列,LIS)

A - Bridging Signals Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu Submit Status Practice ZOJ 1986 Description 'Oh no, they've done it again', cries the chief designer at the Waferland chip factory. Once more the routing designer

uva103(最长递增序列,dag上的最长路)

题目的意思是给定k个盒子,每个盒子的维度有n dimension 问最多有多少个盒子能够依次嵌套 但是这个嵌套的规则有点特殊,两个盒子,D = (d1,d2,...dn) ,E = (e1,e2...en) 只要盒子D的任意全排列,小于盒子E,那么就说明 盒子D能放入盒子E中,其实就是将两个盒子的维度排序,如果前一个盒子的维度依次小于后一个盒子,那么就说明前一个盒子能放入后一个盒子中 这个题目能够转化为最长递增子序列. 首先将盒子的维度从小到大排序,然后将k个盒子,按照排序后的第一维度从小到大排

矩形网格中寻找最长递增序列

在矩形网格中寻找最长的递增序列 比如如下网格 97,47,56,36 35,57,41,13 89,36,98,75 25,45,26,17 结果要求输出 17, 26, 36, 41, 47, 56, 57, 97 基本想法就是对图中的每一个点都当作起始点试一编 将序列最长的保存起来 最后输出 代码如下 使用java编写 import java.util.ArrayList; public class 最长递增序列 { static int[][] rect={ {97,47,56,36},

POJ 2533 Longest Ordered Subsequence 最长递增序列

Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK), where 1 <= i1 < i2 < ... < iK <= N. For example, seque

数据结构与算法学习之路:LIS——最长递增序列的动态规划算法和二分思想算法

一.最长递增序列的问题描述: 求一个整数序列的最长递增子序列,子序列不要求是连续的.例如: Input:4,6,9,6,7,6,3,8,10:Output:5 二.解决方法: 1.用动态规划的方法解决.从问题我们可以知道,我们最终得到的最长递增子序列,其任意一段子序列也是对应序列中的最长子序列.这样说可能不好理解,就以上面的例子来说: 最长子序列为:4,6, 7, 8, 10.在这段子序列的子序列里选一个,例如:4,6,7.则4,6,7也是4,6,9,6,7,6,3这段序列的最长子序列. 对于动

Leetcode 674.最长递增序列

最长递增序列 给定一个未经排序的整数数组,找到最长且连续的的递增序列. 示例 1: 输入: [1,3,5,4,7] 输出: 3 解释: 最长连续递增序列是 [1,3,5], 长度为3. 尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为5和7在原数组里被4隔开. 示例 2: 输入: [2,2,2,2,2] 输出: 1 解释: 最长连续递增序列是 [2], 长度为1. 注意:数组长度不会超过10000. 思路 1 class Solution { 2 public int find

最长递增子序列(输出最长递增序列 及其长度)

最长递增子序列的解法有很多种,常用的有最长公共子序列法.动态规划.记录所有递增序列长度最大值的方法. 最长公共子序列法:如例子中的数组A{5,6, 7, 1, 2, 8},则我们排序该数组得到数组A‘{1, 2, 5, 6, 7, 8},然后找出数组A和A’的最长公共子序列即可.显然这里最长公共子序列为{5, 6, 7, 8},也就是原数组A最长递增子序列. 在http://blog.csdn.net/yysdsyl/article/details/4226630中有详细解释. 动态规划:参见h

游戏之消除(最长递增序列)

描述 zzx和city一直喜欢一起玩游戏,某一天zzx做了一个丧心病狂的消消乐游戏,游戏是这样的,zzx随机生成一个序列让city从前往后寻找5个数ai(1<=i<=5)如果5个数ai满足a1<a2<a3<a4<a5则可以消除这5个数,然而目前出现了一种情况,就是zzx和city不清楚这个序列还有没有可以消除的方案,所以想请你帮忙判断一下. 输入 输入数据有多组,输入到文件结束为止. 第一行输入一个N(106>=N>=5). 第二行输入N个zzx随机生成的序

[leetcode]最长递增序列

class Solution { public: int lengthOfLIS(vector<int>& nums) { int n=nums.size(); if(n==0) return 0; vector<int> maxv(n+1); maxv[0]=INT_MIN; maxv[1]=nums[0]; vector<int> lis(n); lis[0]=1; int nMaxLen=1; for(int i=1;i<n;i++) { int j