题目相关
题目链接
AtCoder Beginner Contest 184 C 题,https://atcoder.jp/contests/abc184/tasks/abc184_c。
Problem Statement
There is an infinite two-dimensional grid, and we have a piece called Super Ryuma at square (r1,c1). (Ryu means dragon and Ma means horse.) In one move, the piece can go to one of the squares shown below:
More formally, when Super Ryuma is at square (a,b), it can go to square (c,d) such that at least one of the following holds:
- a+b=c+d
- a−b=c−d
- |a−c|+|b−d|≤3
Find the minimum number of moves needed for the piece to reach (r2,c2) from (r1,c1).
Input
Input is given from Standard Input in the following format:
r1 c1
r2 c2
Output
Print the minimum number of moves needed for Super Ryuma to reach (r2,c2) from (r1,c1).
Samples1
Sample Input 1
1 1
5 6
Sample Output 1
2
Explaination
We need two moves - for example, (1,1)→(5,5)→(5,6).
Samples2
Sample Input 2
1 1
1 200001
Sample Output 2
2
Explaination
We need two moves - for example, (1,1)→(100001,100001)→(1,200001).
Samples3
Sample Input 3
2 3
998244353 998244853
Sample Output 3
3
Explaination
We need three moves - for example, (2,3)→(3,3)→(−247,253)→(998244353,998244853).
Samples4
Sample Input 4
1 1
1 1
Sample Output 4
0
Constraints
- All values in input are integers.
- 1≤r1,c1,r2,c2≤10^9
题解报告
题目翻译
有一个无限的二维网格,在坐标 (r1, c1) 处有一个超级龙马,每次这个超级龙马可以移动如上图的位置。更加准确的说,当超级龙马在坐标 (a, b),它可以移动到坐标 (c, d) 只要满足下面的条件:
- a+b=c+d
- a−b=c−d
- |a−c|+|b−d|≤3
请找出从 (r1, c1) 移动到 (r2, c2) 的最少的移动步数。
移动方法分析
规则一:a+b=c+d
当前位置为 (a, b)。
1、我们向右下移动一格,对应的坐标为 (a-1, b+1);
2、我们向右下移动 n 格,对应的坐标为 (a-n, b+n);
3、我们向左上移动一格,对应的坐标为 (a+1, b-1);
4、我们向左上移动 n 格,对应的坐标为 (a+n, b- n);
我们可以发现,满足条件 c+d=a+b,也就是满足条件一。也就是副对角线方向运动,如下图所示。
规则二:a-b=c-d
当前位置为 (a, b)。
1、我们向左下移动一格,对应的坐标为 (a+1, b+1);
2、我们向左下移动 n 格,对应的坐标为 (a+n, b+n);
3、我们向右上移动一格,对应的坐标为 (a-1, b-1);
4、我们向右上移动 n 格,对应的坐标为 (a-n, b- n);
我们可以发现,满足条件 c-d=a-b,也就是满足条件二。也就是主对角线方向运动,如下图所示。
规则三:|a−c|+|b−d|≤3
自然就是图片中中间部分。如下图所示。
下面我们根据这个来分析一下样例数据。
样例数据分析
样例数据 1
根据样例数据 1,我们需要从 (1, 1) 到 (5, 6)。
先用规则二,沿着主对角线移动,从 (1, 1) 移动到 (5, 5);
再用规则三,从 (5,5) 移动到 (5, 6)。
样例数据 2
根据样例数据 2,我们需要从 (1, 1) 到 (1, 200001)。
先用规则二,沿着主对角线移动,从 (1, 1) 移动到 (100001, 100001);
再用规则一,沿着副对角线移动,从 (100001, 100001) 移动到 (1, 200001)。
样例数据 3
根据样例数据 3,我们需要从 (2, 3) 到 (998244353, 998244853)。
先规则三,从 (2,3) 到 (3, 3);
再用规则一,沿着副对角线移动,从 (3, 3) 到 (-247, 253);
再用规则二,沿着主对角线移动,从 (-247, 253) 移动到 (998244353, 998244853)。
题目分析
本题又是一个数学题。根据上面的分析,我们可以总结出,从 (r1, c1) 移动到 (r2, c2),超级龙马的移动可能有以下几种可能:
移动次数为 0 次
这个比较简单。也就是起点坐标和终点坐标重合,即 r1==r2 && c1==c2。
移动次数为 1 次
也就是超级龙马可以根据任意一条规则从 (r1, c1) 移动到 (r2, c2)。这样,有三条规则可以满足这个要求。
根据规则一,可以得到条件为 r1+r2==c1+c2;
根据规则二,可以得到条件为 r1-r2==c1-c2;
根据规则三,可以得到条件为 abs(r1-r2)+abs(c1-c2)<=3。
移动次数为 2 次
这是一个组合问题,也就是超级龙马要使用两次规则。我们可以通过遍历也就是先按照规则三移动一次,再判断利用其他规则能否到达目的地即可。具体的实现可以参看下面的 AC 代码。
还有一个特殊情况是起点坐标之和和终点坐标之和奇偶性相同。参考样例输入 2。
移动次数为 3 次
剩下的情况就移动三次肯定可以到达。
AC 参考代码
//https://atcoder.jp/contests/abc184/tasks/abc184_c
//C - Super Ryuma
#include <bits/stdc++.h>
using namespace std;
//如果提交到OJ,不要定义 __LOCAL
#define __LOCAL
int main() {
#ifndef __LOCAL
//这部分代码需要提交到OJ,本地调试不使用
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#endif
int r1,c1,r2,c2;
cin>>r1>>c1>>r2>>c2;
int ans;
if (r1==r2 && c1==c2) {
ans=0;
} else if (r1+c1==r2+c2) {
ans=1;
} else if (r1-c1==r2-c2) {
ans=1;
} else if (abs(r1-r2)+abs(c1-c2)<=3) {
ans=1;
} else if ((r1+c1)%2==(r2+c2)%2) {
ans=2;
} else {
ans=3;
bool flag=true;
for (int i=-3; i<=3 && true==flag; i++) {
for (int j=-3; j<=3; j++) {
//判断不能操作3
if (abs(i)+abs(j)<=3) {
//计算新位置
int xx=r2+i;
int yy=c2+j;
if (r1+c1==xx+yy) {
ans=2;
flag=false;
break;
}
if (r1-c1==xx-yy) {
ans=2;
flag=false;
break;
}
if (abs(r1-xx)+abs(c1-yy)<=3) {
ans=2;
flag=false;
break;
}
}
}
}
}
cout<<ans<<"\n";
#ifdef __LOCAL
//这部分代码不需要提交到OJ,本地调试使用
system("pause");
#endif
return 0;
}
注意,我上面的写法只是为了方便自己在 VsCode 上调试。
时间复杂度
O(1)。
空间复杂度
O(1)。