不难发现,如果想要从 \((x_i,y_i)\) 走到 \((x_{i+1},y_{i+1})\),所需要的时间最少是 \(|x_{i+1}-x_i|+|y_{i+1}-y_i|\)。
同时,走的时间是 \(t_{i+1}-t_i\)。
那么初步判断,当距离大于时间,也就是说走最短路也没法按时走到,就一定不可能。
由此我们假设距离是 \(dis\),时间差是 \(td\),就可以写出以下代码:
if(dis>td){
cout<<"No"<<endl;
return 0;
}
接下来,我们考虑能走到的情况。正好走到的情况一定最好,但是如果多的话就不一定了。考虑简化问题,我们先让这个角色沿最短路走到 \((x_{i+1},y_{i+1})\)。
然后根据题目所说,当现在位置是 \((x,y)\),一次可以走到 \((x+1,y)\),\((x-1,y)\)。那么我们不停让此角色左右反复弹跳不就是了?
形象点,当我们走到 \((x_{i+1},y_{i+1})\) 时,如果有多余时间我们就往右走,然后下一步走回来,不停循环。
那么多余的时间求法就是用 \(td-dis\)。我们注意到,当多余的时间是偶数时,我们可以反复弹跳若干次后回来。不过当多余的时间是奇数时,我们在某次弹到右边就回不来了。
所以,可以写出一下判断代码(这里假设多余的时间还是叫做 \(td\))
if(td%2==1){
cout<<"No"<<endl;
return 0;
}
完整代码:
#include<iostream>
#include<cmath>
using namespace std;
int main(){
int n;
cin>>n;
int t[n+1];
int x[n+1];
int y[n+1];
x[0]=y[0]=t[0]=0;
for(int i=1;i<=n;++i)
cin>>t[i]>>x[i]>>y[i];
for(int i=1;i<=n;++i){
int dis=abs(x[i]-x[i-1])+abs(y[i]-y[i-1]);
int td=t[i]-t[i-1];
if(dis>td){
cout<<"No"<<endl;
return 0;
}
td-=dis;
if(td%2==1){
cout<<"No"<<endl;
return 0;
}
}
cout<<"Yes"<<endl;
}
AC记录:https://www.luogu.com.cn/record/51672719,请指挥使放心审核!