跳马(多源BFS变种,每个起点有步数限制)
补充几个测试样例
输入
3 2
. .
2 .
. .
输出
0
输入
3 5
4 7 . 4 8
4 7 4 4 .
7 . . . .
输出
17
输入
3 4
. . . .
. 2 . .
. . . .
输出
0
输入
3 4
. . . .
. 2 2 .
. . . .
输出
-1
本题很坑爹的地方在于,输入的字符串还用空格分开,所以读入时不能用读连续字符串的方法,例如
读字符串数组(n * m
字符矩阵,中间无空格)char g[N][N]
写法
for (int i = 0; i < n; i++) scanf("%s", g[i]);//读取
for (int i = 0; i < n; i++) printf("%s\n", g[i]);//输出写法1
for (int i = 0; i < n; i++) puts(g[i]);//输出写法2
只能当成矩阵一个一个读,就和读int型二维矩阵一样。
分析:本题数据量不大且因为每个点有移动步数限制,所以采用每个点都搜一次的方法,搜完一个点,dist数组中存的就是该点到其余所有位置的最小步数,更新到total数组中,如果dist[i][j] == -1
,或dist[i][j] > step
,则说明该点不可达,在total中标记为-1.
最后遍历一遍total数组,把所有-1
改成正无穷,再取最小值输出即可。
C++代码
/*** Created by Tshaxz on 25-1-16.*/
#include <iostream>
#include <cstring>
#include <queue>using namespace std;typedef pair<int, int> PII;const int N = 30, INF = 0x3f3f3f3f;int n, m;
char g[N][N];
int dist[N][N], total[N][N];
int dx[8] = {1, 2, 2, 1, -1, -2, -2, -1};
int dy[8] = {2, 1, -1, -2, -2, -1, 1, 2};void bfs(int x, int y, int step)
{memset(dist, -1, sizeof dist);queue<PII> q;dist[x][y] = 0;q.push({x, y});while (q.size()){auto [x, y] = q.front();q.pop();for (int i = 0; i < 8; i++){int a = x + dx[i], b = y + dy[i];if (a < 0 || a >= n || b < 0 || b >= m) continue;if (dist[a][b] != -1) continue;if (dist[a][b] > step) continue;dist[a][b] = dist[x][y] + 1;q.push({a, b});}}
}int main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n >> m;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)cin >> g[i][j];for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)if (g[i][j] != '.'){int step = g[i][j] - '0';bfs(i, j, step);for (int x = 0; x < n; x++)for (int y = 0; y < m; y++){if (dist[x][y] > step) total[x][y] = -1;else if (total[x][y] != -1) total[x][y] += dist[x][y];}}int res = INF;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++){if (total[i][j] == -1) total[i][j] = INF;res = min(res, total[i][j]);}if (res == INF) res = -1;cout << res << '\n';return 0;
}
debug版代码,可以输出dist与total数组查看
/*** Created by Tshaxz on 25-1-16.*/
#include <iostream>
#include <cstring>
#include <queue>using namespace std;typedef pair<int, int> PII;const int N = 30, INF = 0x3f3f3f3f;int n, m;
char g[N][N];
int dist[N][N], total[N][N];
int dx[8] = {1, 2, 2, 1, -1, -2, -2, -1};
int dy[8] = {2, 1, -1, -2, -2, -1, 1, 2};void bfs(int x, int y, int step)
{memset(dist, -1, sizeof dist);queue<PII> q;dist[x][y] = 0;q.push({x, y});// printf("step: %d\n", step);while (q.size()){auto [x, y] = q.front();q.pop();for (int i = 0; i < 8; i++){int a = x + dx[i], b = y + dy[i];if (a < 0 || a >= n || b < 0 || b >= m) continue;if (dist[a][b] != -1) continue;if (dist[a][b] > step) continue;dist[a][b] = dist[x][y] + 1;q.push({a, b});}}
}// void print1()
// {
// printf("dist: \n");
// for (int i = 0; i < n; i++)
// {
// for (int j = 0; j < m; j++) printf("\t%d\t", dist[i][j]);
// puts("");
// }
// }// void print2()
// {
// printf("total:\n");
// for (int i = 0; i < n; i++)
// {
// for (int j = 0; j < m; j++) printf("\t%d\t", total[i][j]);
// puts("");
// }
// }int main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n >> m;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)cin >> g[i][j];for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)if (g[i][j] != '.'){int step = g[i][j] - '0';bfs(i, j, step);// printf("当前的马:g[%d][%d]:%c\n", i, j, g[i][j]);// print1();for (int x = 0; x < n; x++)for (int y = 0; y < m; y++){if (dist[x][y] > step) total[x][y] = -1;else if (total[x][y] != -1) total[x][y] += dist[x][y];}// print2();}int res = INF;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++){if (total[i][j] == -1) total[i][j] = INF;res = min(res, total[i][j]);}if (res == INF) res = -1;cout << res << '\n';return 0;
}