UVALive 7374 Racing Gems - dp,最长上升子序列
2016-08-22 10:39
344 查看
题意:赛车从x轴出发往前走,竖直方向速度为v,水平速度要在-v/r到v/r之间,给出n个钻石的坐标,问赛车最多能拿到多少颗钻石。
在打组队赛的时候,我就想到了动态规划加线段树优化或者是最长上升子序列的nlog(n)算法,但是都没有想到具体该怎么处理,之后证实这两种方法都能实现,不过由于线段树还是比较麻烦,所以只实现了最长上升子序列的方法。
这是一个很巧妙的处理,对于每一个钻石的坐标,都能根据水平速度与竖直速度的关系映射到x轴上的一个区间上,对应的y越大,区间长度就越长。对于两个区间,如果区间a的起点大于等于区间b的起点,而且区间a的终点小于等于b的终点,那么就可以先拿a点的钻石,之后去拿b点的钻石,如果a的起点小于b的起点的话,无论终点怎样都不可能先拿a再拿b,于是问题就变成了对于n个区间,按照区间的起点降序排序,然后找终点的最长不下降子序列。数据量比较大,但是最长上升子序列有nlog(n)的算法,我抄的模板,也并不是很懂。#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
typedef long long ll;
struct node {
ll b, e;
}id[MAXN];
bool cmp(node a, node b) {
if(a.b != b.b)
return a.b > b.b;
return a.e < b.e;
}
ll dp[MAXN];
int Search(ll num, int low, int high) {
int mid;
while(low <= high) {
mid = (low + high) >> 1;
if(num >= dp[mid]) low = mid + 1;
else high = mid - 1;
}
return low;
}
int DDPP(int n) {
int i, len = 1, pos;
dp[1] = id[1].e;
for(i = 2; i <= n; i++) {
if(id[i].e >= dp[len]) {
len = len + 1;
dp[len] = id[i].e;
}
else {
pos = Search(id[i].e, 1, len);
dp[pos] = id[i].e;
}
}
return len;
}
int main() {
int i, n, r, w, h, x, y;
while(~scanf("%d%d%d%d", &n, &r, &w, &h)) {
for(i = 1; i <= n; i++) {
scanf("%d%d", &x, &y);
id[i].b = (ll)x * r - y;
id[i].e = (ll)x * r + y;
}
sort(id + 1, id + n + 1, cmp);
printf("%d\n", DDPP(n));
}
return 0;
}
在打组队赛的时候,我就想到了动态规划加线段树优化或者是最长上升子序列的nlog(n)算法,但是都没有想到具体该怎么处理,之后证实这两种方法都能实现,不过由于线段树还是比较麻烦,所以只实现了最长上升子序列的方法。
这是一个很巧妙的处理,对于每一个钻石的坐标,都能根据水平速度与竖直速度的关系映射到x轴上的一个区间上,对应的y越大,区间长度就越长。对于两个区间,如果区间a的起点大于等于区间b的起点,而且区间a的终点小于等于b的终点,那么就可以先拿a点的钻石,之后去拿b点的钻石,如果a的起点小于b的起点的话,无论终点怎样都不可能先拿a再拿b,于是问题就变成了对于n个区间,按照区间的起点降序排序,然后找终点的最长不下降子序列。数据量比较大,但是最长上升子序列有nlog(n)的算法,我抄的模板,也并不是很懂。#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
typedef long long ll;
struct node {
ll b, e;
}id[MAXN];
bool cmp(node a, node b) {
if(a.b != b.b)
return a.b > b.b;
return a.e < b.e;
}
ll dp[MAXN];
int Search(ll num, int low, int high) {
int mid;
while(low <= high) {
mid = (low + high) >> 1;
if(num >= dp[mid]) low = mid + 1;
else high = mid - 1;
}
return low;
}
int DDPP(int n) {
int i, len = 1, pos;
dp[1] = id[1].e;
for(i = 2; i <= n; i++) {
if(id[i].e >= dp[len]) {
len = len + 1;
dp[len] = id[i].e;
}
else {
pos = Search(id[i].e, 1, len);
dp[pos] = id[i].e;
}
}
return len;
}
int main() {
int i, n, r, w, h, x, y;
while(~scanf("%d%d%d%d", &n, &r, &w, &h)) {
for(i = 1; i <= n; i++) {
scanf("%d%d", &x, &y);
id[i].b = (ll)x * r - y;
id[i].e = (ll)x * r + y;
}
sort(id + 1, id + n + 1, cmp);
printf("%d\n", DDPP(n));
}
return 0;
}
相关文章推荐
- UVALive-7374-Racing Gems(最长上升子序列O(n*logn))
- UVALive 7374 Racing Gems (最长上升子序列--二分法)
- POJ1609 UVALive2815 UVA1196 ZOJ1787 Tiling Up Blocks【二维最长上升子序列+DP】
- UVA 10534-Wavio Sequence(dp_正序逆序最长上升子序列)
- UVA 10154 Weights and Measures(贪心+DP最长上升子序列)
- UVA 10131 Is Bigger Smarter?(DP最长上升子序列)
- UVA12511 - Virus(DP+最长公共上升子序列)
- UVa 10534 - Wavio Sequence (简单DP 最长上升下降子序列)
- DP实例之最长上升子序列LIS
- hdu 1160 dp (二维最长上升子序列 记录路径
- DP-最长上升子序列(一维)
- 【基础练习】【线性DP】codevs1576 最长严格上升子序列题解
- 【dp】哈理工-1116-选美大赛(最长上升子序列和打印位置)
- UVA 12511/CSU 1120 virus 最长公共上升子序列
- dp专题 第一题最长上升子序列
- poj2533--Longest Ordered Subsequence(dp:最长上升子序列)
- POJ-1836 Alignment (Romania OI 2002 线性dp 最长上升子序列)
- 【序列型DP】最长严格上升子序列
- 导弹拦截(dp-最长不上升子序列)
- UVA - 10635 Prince and Princess (二分法 求最长上升子序列)