4723: [POI2017]Flappy Bird

本文介绍了一款名为《飞扬的小鸟》的游戏算法实现。玩家需控制小鸟避开障碍物到达终点,通过数学方法计算到达指定位置所需的最少点击次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4723: [POI2017]Flappy Bird

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 246   Solved: 99
[ Submit][ Status][ Discuss]

Description

《飞扬的小鸟》是一款风靡的小游戏。在游戏中,小鸟一开始位于(0,0)处,它的目标是飞到横坐标为X的某个位置
上。每一秒,你可以选择点击屏幕,那么小鸟会从(x,y)飞到(x+1,y+1),或者不点击,那么小鸟会飞到(x+1,y-1)
。在游戏中还有n个障碍物,用三元组(x[i],a[i],b[i])描述,表示在直线x=x[i]上,y<=a[i]或者y>=b[i]的部分
都是障碍物,碰到或者擦边都算游戏失败。请求出小鸟从(0,0)飞到目的地最少需要点击多少次屏幕。

Input

第一行包含两个整数n(0<=n<=500000),X(1<=n<=10^9)。
接下来n行,每行三个整数x[i],a[i],b[i](0<x[i]<X,-10^9<=a[i]<b[i]<=10^9)。
数据保证x[i]<x[i+1]。

Output

如果无论如何都飞不到目的地,输出NIE,否则输出点击屏幕的最少次数。

Sample Input

4 11
4 1 4
7 -1 2
8 -1 3
9 0 2

Sample Output

5

HINT


Source

[ Submit][ Status][ Discuss]

对于第i根水管,不妨假设由x = 0前进到x = xi的时候,点击屏幕Ai次,不点击Bi次
那么,有Ai + Bi = xi  ai < Ai - Bi < bi,稍微改写下,得到(ai + xi) / 2 < Ai < (bi + xi) / 2
说明对于每根柱子,想要安全飞过去,之前的点击次数需要在某个区间内
这样,从左往右推一边就解决了,初始区间设为[0,0]
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int maxn = 5E5 + 50;
typedef long long LL;
typedef double DB;
const LL INF = 1E16;

int n,X;
LL L,R,a[maxn],b[maxn],x[maxn];

int getint()
{
	char ch = getchar(); int ret = 0,A = 1;
	while (ch < '0' || '9' < ch)
	{
		if (ch == '-') A = -1;
		ch = getchar();
	}
	while ('0' <= ch && ch <= '9')
		ret = ret*10 + ch - '0',ch = getchar();
	return ret * A;
}

int main()
{
	
	n = getint(); X = getint();
	for (int i = 1; i <= n; i++)
		x[i] = getint(),a[i] = getint(),b[i] = getint();
	++n; x[n] = X; a[n] = -INF; b[n] = INF;
	for (int i = 1; i <= n; i++)
	{
		LL l = floor((DB)(a[i] + x[i]) / 2.00) + 1LL;
		LL r = ceil((DB)(b[i] + x[i]) / 2.00) - 1LL;
		LL delta = x[i] - x[i-1]; 
		if (R + delta < l) {puts("NIE"); return 0;}
		if (L > r) {puts("NIE"); return 0;} if (L < l) L = l;
		if (R > r) R = r; else R = min(R + delta,r);
		if (L > R) {puts("NIE"); return 0;}
	}
	cout << L;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值