10676 涂鸦跳跃
10676 涂鸦跳跃
该题有题解
时间限制:1000MS 内存限制:65535K
提交次数:240 通过次数:19
题型: 编程题 语言: G++;GCC
Description
你玩过曾经风靡一时的手机游戏涂鸦跳跃吗?
这是个很简单的小游戏,我们的主角弹簧小怪物会不知疲倦地往上跳,而我们需要做的就是控制他的方向,跳得越高得分也越高。
有一天,Sirius突然想到一个问题,假如给定一个起始平台和终止平台,那么弹簧小怪物是否能够借助一系列平台从起始平台跳到终止平台呢?
我们假定屏幕的左下角是直角坐标系的原点(0,0),往右则x值增大,往上则y值增大。屏幕的最右端的坐标是x = M。
每个平台表示为[x1, x2, y],分别为平台的左端点x值、右端点x值以及高度,当然平台是平行于x轴的。弹簧小怪物在
竖直方向上最多可以跳h,在水平方向上最多可以跳w,竖直跳和水平跳是可以同时进行的。由于游戏画面的移动,小怪物
是不能跳到比它当前所在平台低的平台的,但是可以跳到当前所在平台的任何位置。小怪物可以穿越屏幕左边到达右侧,
也可以穿越屏幕右边到达左侧,当然穿越跳也要受到水平弹跳力w的限制。为了简化题目,我们假定只要在小怪物弹跳能力
范围内的平台都是可以到达的,即使一个平台恰好挡在另一个平台的上方!并且,我们不考虑平台的厚度,小怪物看作一个点,
不同平台不会有重叠部分。到达终止平台的任何位置,我们都认为它已经到达。
输入格式
第一行只有一个正整数T,表示题目共有T组数据
接下来是T组数据。每组数据的第一行是4个正整数n、M、w、h,分别表示平台个数、屏幕最右端的x坐标、小怪物的水平跳跃能力、
小怪物的竖直跳跃能力,2 <= n <= 1000,0 < w < M <= 10000,0 < h < 1000。接下来n行,每一行有
三个正整数x1 x2 y(M >= x2 > x1 >= 0, 10000 >= y >= 0),分别表示平台的左端点x值、右端点x值以及高度。
在这n行中,第一行表示的是起始平台,最后一行表示的是终止平台,平台的高度不一定按顺序排列。
输出格式
如果小怪物能从起始平台到达终止平台,输出yes;否则输出no。
输入样例
3
5 100 20 20
1 5 0
25 81 20
1 4 40
5 6 19
1 3 50
2 100 20 20
0 5 0
80 100 100
3 100 20 20
0 5 0
3 7 3
8 14 10
输出样例
yes
no
yes
提示
当穿越的时候,我们认为屏幕最左侧x=0和屏幕最右侧x=M是等价的。比如样例输入1,第1个平台可以跳到第2个和第4个,
第2个平台可以跳到第3个(穿越跳,100-81+1-0=20<=w=20),第3个可以跳到第5个,第4个可以跳到第2个。故答案是yes。
来源
by sirius
作者
admin
题解
题意大概是给你n条线段,有个物体可以往上和左右进行跳跃,并且限制了跳跃的范围,问能否从起始线段跳到终止线段。
大概题解写在代码注释上:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define X first
#define Y second
#define clr(u,v); memset(u,v,sizeof(u));
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1010;
const int INF=0x3f3f3f3f;
struct node {
int x,y,high,flag,index;
//x和y分别代表线段的左右端点坐标,high代表线段高度,flag表示这条线段是否能到达,index代表线段原来的下标
bool operator < (const node &a) const {
return this->high<a.high;
}
}N[maxn];
int n,m,w,h;
//判断线段j能否到达线段i
bool ok(int i,int j) {
if (N[j].y+w >= m) {
if (N[i].x >= N[j].x) return 1;
else if (N[j].y+w-m >= N[i].x) return 1;
} else {
if (N[j].y+w >= N[i].x) return 1;
}
if (N[j].x-w<0) {
if (N[i].x <= N[j].x) return 1;
else if (N[j].x-w+m <= N[i].y) return 1;
} else {
if (N[j].x-w <= N[i].y) return 1;
}
return 0;
}
int main() {
int T;
scanf("%d",&T);
while (T--) {
scanf("%d%d%d%d",&n,&m,&w,&h);
for (int i=0;i<n;++i) {
scanf("%d%d%d",&N[i].x,&N[i].y,&N[i].high);
N[i].index=i,N[i].flag=0;
}
N[0].flag=1;//起始边可以到达
sort(N,N+n);
//暴力枚举高度比当前线段高度低的边,且该边可以被到达,判断当前线段能否被到达
for (int i=1;i<n;i++) {
for (int j=0;j<i;++j) {
if (N[j].flag && N[i].high-N[j].high<=h && ok(i,j)) {
N[i].flag=1;//如果能到达,进行标记
break ;
}
}
}
//看下标为n-1的边(排序前的最后一条线段)能否被到达,可以的话输出yes,否则输出no
for (int i=0;i<n;i++) {
if (N[i].index == n-1) {
if (N[i].flag) puts("yes");
else puts("no");
break ;
}
}
}
return 0;
}
/*
3
2 100 1 100
80 99 100
0 5 0
2 100 1 100
80 99 0
0 5 100
2 100 1 100
0 5 0
80 99 100
*/
/*
no
yes
yes
*/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~