【题目来源】
https://www.acwing.com/problem/content/1513/
【题目描述】
小王特别喜欢玩 flappy birds,但是他比较菜,所以向大家寻求帮助,游戏规则大家都懂,每一秒如果点击屏幕,小鸟会从 (x,y) 飞到 (x+1,y+1);如果不点击屏幕,小鸟则会飞到 (x+1,y−1)。
笨鸟初始坐标 (0,0),要飞到横坐标为 X 的地方,纵坐标不做要求。
沿途有一些障碍,用 (x0,a,b) 的形式给出,表示在横坐标为 x0 的地方 y≤a 和 y≥b 的地方都是障碍,碰到或者擦边都算游戏失败。
也就是说,小鸟通过此横坐标时纵坐标必须在 (a,b) 这个范围内,且纵坐标不等于 a 或 b。
如果这只笨鸟根本没有办法飞到终点横坐标,则输出”Stupid bird!”(不包含引号)。
否则输出通过每个障碍以及终点横坐标时所需要点击屏幕的最少次数。
注意:在考虑通过某个障碍所需最少点击次数时,不用考虑此操作对通过后面障碍物的影响以及是否能够确保通关。
【输入格式】
第一行两个整数 n,X。
接下来 n 行,每行三个整数 (xi,ai,bi),含义见题目描述。
【输出格式】
若笨鸟飞不到终点,输出“Stupid bird!”(不含引号) 。
否则输出包含 n+1 行。
前 n 行,每行一个整数,表示通过每个障碍时所需最少的点击次数。
最后一行,表示到达终点横坐标时所需的最少点击次数。
【数据范围】
0≤n≤5×10^5
1≤X≤10^9
0<xi<X
−10^9≤ai<bi≤10^9
。
【输入样例】
4 11
4 1 4
7 -1 2
8 -1 3
9 0 2
【输出样例】
3
4
4
5
5
【算法分析】
● 本题题意可参见原型游戏 flappy bird:https://flappybird.io/
● 求解本题,请参考如下示意图。特别要注意 b 和 a 在图中的位置以及 up 及 down 的含义。显然,up=up+x-last,down=down-(x-last)。
● 不管障碍物距 0 点的距离 x 是偶数还是奇数,能够到达的 y 值均是离散的且相差 2。之所以离散,是因为小鸟的坐标是按秒更新的。且,若障碍物距 0 点的距离 x 值是偶数/奇数,则能够到达的离散 y 值也是偶数/奇数。
据上,便有了判断奇偶性的要求。代码如下所示。
if((x&1) != (a&1)) a++;
if((x&1) != (b&1)) b--;
即,若 x 与 a 的奇偶性不一致,则 a++;若 x 与 b 的奇偶性不一致,则 b++。
(注意:a、b 在示意图中的位置)
此代码用位运算 & 判断奇偶性。即,若 x&1 为真,则 x 为奇数;否则,x 为偶数。
● 通过每个障碍时所需最少的点击次数
设 x 是障碍物距 0 点的距离,y 是在 x 处时“笨鸟”通过障碍物的坐标,up 是点击次数,则可知 up-(x-up)=y,也即 up=(x+y)/2。若要使 up 最小,则取 y 的最小值 down,故得通过每个障碍时所需最少的点击次数为 up=(x+down)/2。此处的 up 对应于下面代码中的 imin[i]。
【算法代码】
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int imin[N]; //minimum number of per step
bool flag=true;
int up,down; //scope
int last; //Coordinates of the last obstacle
int main() {
int n,X;
cin>>n>>X;
for(int i=1; i<=n; i++) {
int x,a,b;
cin>>x>>a>>b;
up=up+x-last;
down=down-(x-last);
//The range that the bird can fly
a++,b--; //can't reach to a and b
if((x&1) != (a&1)) a++;
if((x&1) != (b&1)) b--;
up=min(up,b);
down=max(down,a);
//Update the bird interval
if(up<down) {
flag=false;
break;
}
imin[i]=(x+down)/2;
last=x;
}
if(!flag) cout<<"Stupid bird!"<<endl;
else {
for(int i=1; i<=n; i++) cout<<imin[i]<<endl;
cout<<imin[n]<<endl;
}
return 0;
}
/*
in:
4 11
4 1 4
7 -1 2
8 -1 3
9 0 2
out:
3
4
4
5
5
*/
【参考文献】
https://www.luogu.com.cn/problem/P1941
https://www.acwing.com/solution/content/88484/
https://www.acwing.com/solution/content/23727/