题目:
要去一个任务点(任务点用字符”T“ 表示)完成任务, 地图上多个传送点(传送点用字符"X" 表示)。可以选择任意一个传送点作为起点, 请问哪些传送点到任务点的距离最短。
在地图上只能上下左右移动,不能斜着移动。
输入描述:
第一行包含2个整数N和M, 接下来N行每行包含M个字符, 字符”T“表示任务点(只有一个), 字符”X“表示传送点,字符”0“表示可以通行的路, 字符”1“表示不可以通行的障碍物。
输出描述:
输出两行,第一行包含一个整数,表示传送点到任务点的最短距离,第二行包含到任务点距离最短的所有传送点的坐标(先行后列,都是从0开始计数),有多个坐标时按照字典序排列(行号小的排在前面, 行号一样的列号小的排在前面)。
不能到达只输出一行0.
解决方案:
(1)java实现
package com.freewolf.byteDance;
import java.util.*;
/**
* @author fgs
* @since 2020/9/26 19:13
*/
public class pingduoduo2 {
private static int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
private static int row;
private static int col;
public static char[][] deepCopy(char[][] grid){
char[][] mask = new char[grid.length][grid[0].length];
for(int i = 0; i < grid.length; ++i){
for (int j = 0; j < grid[0].length; j++) {
mask[i][j] = grid[i][j];
}
}
return mask;
}
public static int shortestPath(char[][] grid, int c, int l){
Queue<int[]> pos = new LinkedList<>();
int[][] length = new int[row][col];
length[c][l] = 1; // 直接用grid[i][j]记录从起点到这个点的最短路径长。按照题意 起点也有长度1
pos.add(new int[]{c,l});
int[] xy = new int[2];
while(!pos.isEmpty()){ // 求最短路径 使用BFS
xy = pos.remove();
if(grid[xy[0]][xy[1]] == 'T') break;
if(grid[xy[0]][xy[1]] == '1') continue; // 无法通行
if(grid[xy[0]][xy[1]] == 'X' && (c != xy[0] && l != xy[1])) continue; // X 不能通行
int preLength = length[xy[0]][xy[1]]; // 当前点的路径长度
for(int i = 0; i < 4; i++){ // 共有四个方向
int newX = xy[0] + directions[i][0];
int newY = xy[1] + directions[i][1];
if(inGrid(newX, newY) && length[newX][newY] == 0){
pos.add(new int[]{newX, newY});
length[newX][newY] = preLength + 1; // 下一个点的路径长度要+1
}
}
}
return grid[xy[0]][xy[1]] != 'T'? Integer.MAX_VALUE: length[xy[0]][xy[1]]; // 如果最后终点的值还是0,说明没有到达
}
private static boolean inGrid(int x, int y){
return x >= 0 && x < row && y >= 0 && y < col;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int M = sc.nextInt();
row = N;
col = M;
Map<Integer, Integer> point = new HashMap<Integer, Integer>();
char[][] grid = new char[N][M];
for(int i = 0; i < N; ++i){
String tmp = sc.next();
char[] chars = tmp.toCharArray();
for(int j = 0; j < M; ++j){
if(chars[j] == 'X'){
point.put(i, j);
}
}
grid[i] = chars;
}
int minLen = Integer.MAX_VALUE;
Map<Integer, Integer> ret = new TreeMap<>();
for(Map.Entry<Integer, Integer> entry: point.entrySet()){
int x = entry.getKey();
int y = entry.getValue();
int len = shortestPath(grid, x, y);
if(len == minLen) ret.put(x, y);
else if(len < minLen) {
ret.clear();
ret.put(x, y);
minLen = len;
}
}
if(minLen == Integer.MAX_VALUE) {
System.out.println(-1);
return;
}
System.out.println(minLen - 1);
for(Map.Entry<Integer, Integer> entry : ret.entrySet()){
System.out.print(entry.getKey() + " " + entry.getValue() + " ");
}
System.out.println();
}
}
/*
5 6
X00100
00000X
01T000
0X1010
00000X
*/
(2)C++实现:
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
static int N, M;
static int directions[4][2] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };
bool inGrid(int newX, int newY) {
return newX >= 0 && newX < N && newY >= 0 && newY < M;
}
int bfs(vector<vector<char>> &grid, int row, int col) {
queue<pair<int, int>> pos;
pos.push(make_pair(row, col));
vector<vector<int>> length(grid.size(), vector<int>(grid[0].size(), 0));
length[row][col] = 1;
pair<int, int> xy;
while (!pos.empty()) {
xy = pos.front();
pos.pop();
if (grid[xy.first][xy.second] == 'T') break;
if (grid[xy.first][xy.second] == 'X' && (xy.first != row && xy.second != col)) continue;
int preLength = length[xy.first][xy.second];
for (int i = 0; i < 4; ++i) {
int newX = xy.first + directions[i][0];
int newY = xy.second + directions[i][1];
if (inGrid(newX, newY) && length[newX][newY] == 0 && grid[newX][newY] != '1') {
pos.push(make_pair(newX, newY));
length[newX][newY] = preLength + 1;
}
}
}
return grid[xy.first][xy.second] != 'T' ? INT_MAX : length[xy.first][xy.second];
}
int main()
{
//int N = 0, M = 0;
cin >> N >> M;
vector<vector<char>> grid(N, vector<char>(M, -1));
vector<pair<int, int>> points;
for (int i = 0; i < N; ++i) {
for (int j = 0; j < M; ++j) {
char tmp;
cin >> tmp;
if (tmp == 'X') points.push_back(make_pair(i, j));
grid[i][j] = tmp;
}
}
int minLen = INT_MAX;
vector<pair<int, int>> ret;
for (int i = 0; i < points.size(); ++i) {
int len = bfs(grid, points[i].first, points[i].second);
if (len == minLen) ret.push_back(points[i]);
else if (len < minLen) {
minLen = min(len, minLen);
ret.clear();
ret.push_back(points[i]);
}
}
if (minLen == INT_MAX) {
cout << -1 << endl;
return 0;
}
cout << minLen - 1 << endl;
for (int i = 0; i < ret.size(); ++i) {
cout << ret[i].first << " " << ret[i].second << " ";
}
cout << endl;
return 0;
}
补充:
如果不需要确定当前遍历到了哪一层,模板如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
如果需要确定遍历到哪一层,模板如下;
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
本文介绍了一个寻找地图上从任意传送点到唯一任务点最短路径的算法问题。提供了Java和C++两种语言的实现方案,并详细解释了如何利用广度优先搜索(BFS)算法来解决该问题。
1810

被折叠的 条评论
为什么被折叠?



