题目描述
小 X 最近对战胜韩国围棋大神李世石的
A
l
p
h
a
G
o
AlphaGo
AlphaGo 很感兴趣,所以小
X
X
X 自己写了一个叫 做
B
e
t
a
G
o
BetaGo
BetaGo的人工智能程序(简称
A
I
AI
AI) , 这个
B
e
t
a
G
o
BetaGo
BetaGo 会做什么呢?
小 X 首先想要让
B
e
t
a
G
o
BetaGo
BetaGo 做到自己在棋盘上落子, 这一点
A
l
p
h
a
G
o
AlphaGo
AlphaGo 是由程序员来完成的。小
X
X
X 的设想是这样的: 在棋盘的边框上放置一个小机器人, 这个小机器人会沿着棋盘的边框移动到最接近落子点的位置,然后伸出它的机械臂将棋子放到棋盘上。 这里面最关键的一步是如何让小机器人在棋盘的边框上沿着最短的路径移动,小
X
X
X 想请你帮他编个程序解决这个问题。
众所周知,围棋棋盘大小为
19
×
19
19 × 19
19×19(如下图所示) , 图中加粗的一圈即为边框。
我们用一对整数 (x, y) 来表示棋盘上第 x 条横线(从下往上数)与第 y 条竖线(从左往右数)的交叉点,如上图中边框上的 A 点用( 6, 1) 表示, B 点用 (10, 19) 表示,小机器人初始时放置在 (x1,y1) 这个位置上, 它想要移动到 (x2, y2) 这个位置上。 (x1, y1) 和(x2, y2) 一定是棋盘边框上的交叉点每一步小机器人可以从当前位置移动到相邻(上下左右)的某个位置上, 即每次可以从 (x, y) 移动到 (x - 1, y) 、 (x + 1, y) 、 (x, y - 1) 、 (x, y + 1) 四个位置中的一个, 但是它不能走出或走进棋盘,也就是说它只能沿着棋盘的边框移动到相邻位置, 这就意味着任一时刻相邻位置都恰好只有两个。
BetaGo 会告诉小机器人最少需要走多少步, 但小 X 还是很担心
B
e
t
a
G
o
BetaGo
BetaGo 有的时候会失控,从而告诉他一个错误值。
为此小 X 只好求助你, 希望你编一个程序计算从
(
x
1
,
y
1
)
(x1, y1)
(x1,y1) 沿着棋盘的边框移动到
(
x
2
,
y
2
)
(x2, y2)
(x2,y2) 最少需 要 走 多 少步 。 上 图 中 从
A
A
A 点
(
6
,
1
)
( 6 , 1 )
(6,1) 移 动 到 B 点
(
10
,
19
)
(10 , 19)
(10,19) 最 少需 要 走
32
32
32 步 , 移 动 路线 是 :
(
6
,
1
)
→
(
5
,
1
)
→
(
4
,
1
)
→
(
3
,
1
)
→
(
2
,
1
)
→
(
1
,
1
)
→
(
1
,
2
)
→
(
1
,
3
)
→
…
…
→
(
1
,
19
)
→
(
2
,
19
)
→
…
…
→
(
10
,
19
)
( 6 , 1 ) → ( 5 , 1 ) → ( 4 , 1 ) → ( 3 , 1 ) → ( 2 , 1 ) → ( 1 , 1 ) → (1 , 2 ) → (1 , 3 ) →……→(1, 19) →(2, 19) →……→(10, 19)
(6,1)→(5,1)→(4,1)→(3,1)→(2,1)→(1,1)→(1,2)→(1,3)→……→(1,19)→(2,19)→……→(10,19)
题目分析
方法一:
三种情况:
(
1
)
(1)
(1)如果对面两个点
(
2
)
(2)
(2)如果相邻直线上的两个点 [
a
b
s
(
x
1
−
x
2
)
+
a
b
s
(
y
1
−
y
2
)
abs(x1-x2)+abs(y1-y2)
abs(x1−x2)+abs(y1−y2)]
(
3
)
(3)
(3)如果在同一条线上[判断
a
b
s
(
x
1
−
x
2
)
abs(x1-x2)
abs(x1−x2) 或
a
b
s
(
y
1
−
y
2
)
abs(y1-y2)
abs(y1−y2)]
Code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll MAXN = 1010, mod = 998244353;
inline int read() {
int x = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}
ll a1, a2, b1, b2, tmx, tmy;
signed main() {
cin >> a1 >> a2 >> b1 >> b2;
if (abs(a1 - b1) == 18) {
tmx = 18 + a2 - 1 + b2 - 1;
tmy = 18 + 19 - a2 + 19 - b2;
}
if (abs(a2 - b2) == 18) {
tmx = 18 + a1 - 1 + b1 - 1;
tmy = 18 + 19 - a1 + 19 - b1;
}
if (a1 == b1)tmx = abs(a2 - b2);
if (a2 == b2)tmx = abs(a1 - b1);
if (tmx + tmy == 0)tmx = abs(a1 - b1) + abs(a2 - b2);
if ((tmx > tmy) && (tmy != 0)) {
cout << tmy;
} else cout << tmx;
return 0;
}
方法二:
爆搜出奇迹!
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll MAXN = 110, mod = 998244353, dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};;
inline int read() {
int x = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}
int a, b, c, d, f[MAXN][MAXN], vis[MAXN][MAXN];
int bfs() {
queue<pair<int, int>> q;
q.push({a, b}), vis[a][b] = 0;
while (q.size()) {
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int X = t.first + dx[i], Y = t.second + dy[i];
if (!f[X][Y]) continue;
if (vis[X][Y] > vis[t.first][t.second] + 1)vis[X][Y] = vis[t.first][t.second] + 1, q.push({X, Y});
if (X == c && Y == d)return vis[X][Y];
}
}
}
int main() {
for (int i = 1; i <= 19; i++)f[i][1] = f[i][19] = f[1][i] = f[19][i] = 1;
memset(vis, 0x3f, sizeof vis);
a = read(), b = read(), c = read(), d = read();
cout << bfs();
return 0;
}