D题:最少步数
思路:
1、对于A、B两点的坐标
(
X
i
,
Y
i
)
(Xi, Yi)
(Xi,Yi), 我们需要计算通过走“日”字型或走“田”字型路径到达
(
1
,
1
)
(1, 1)
(1,1)的最少步数。这个问题等价于从
(
1
,
1
)
(1, 1)
(1,1)出发,以日、田路径,到达某一点
P
(
x
,
y
)
P(x, y)
P(x,y) 的最少步数问题。
2、通过广度优先搜索,可以得到从起点
(
1
,
1
)
(1, 1)
(1,1) 出发,到达定义域
D
:
{
(
x
,
y
)
∣
1
≤
x
≤
100
,
1
≤
y
≤
100
}
\mathbb{D}: \{(x, y) | 1 \leq x \leq 100, 1 \leq y \leq 100\}
D:{(x,y)∣1≤x≤100,1≤y≤100}中任意点
(
x
,
y
)
(x, y)
(x,y)的最少步数值
f
(
x
,
y
)
f(x, y)
f(x,y)。
代码:
#include <bits/stdc++.h>
using namespace std;
int cnt[110][110];//保存定义域内每一点的答案
int dir[12][2] = {{1,2},{2,1},{2,2},{-1,-2},{-2,-1},{-2,-2},{-2, 2}, {2, -2}, {1, -2}, {-1, 2}, {-2,1}, {2, -1}};
//对应6种马的走法与6中田的走法
bool check(int x, int y) //判断一点是否超越了定义范围,是否已经被更短的路径访问过
{
if(x <= 0 || x > 100) return false;
if(y <= 0 || y > 100) return false;
if(cnt[x][y] != 0) return false;
return true;
}
void bfs() //广度优先搜索
{
memset(cnt, 0, sizeof(cnt));
queue<pair<int, int>> q;
q.push({1, 1}); //创建一个空的队列并将(1, 1)设置为出发点
while(!q.empty()) {
auto tmp = q.front();
q.pop();
int x = tmp.first;
int y = tmp.second;
for(int i = 0; i < 12; i++) //每次从队列的首中取出一个点并判断其下一个可行的走向
{
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(check(nx, ny)) {
if(cnt[nx][ny] == 0) cnt[nx][ny] = cnt[x][y] + 1;
else cnt[nx][ny] = min(cnt[x][y] + 1, cnt[nx][ny]);
q.push({nx, ny});
}
}
}
}
int main() {
int a, b, c, d;
scanf("%d %d %d %d", &a, &b, &c, &d);
bfs();
printf("%d\n%d\n", cnt[a][b], cnt[c][d]);
return 0;
}