拜访
原题描述
现在有一个城市销售经理,需要从公司出发,去拜访市内的某位商家,已知他的位置以及商家的位置,但是由于城市道路交通的原因,他每次移动只能在左右中选择一个方向 或 在上下中选择一个方向,现在问他有多少种最短方案到达商家地址。
给定一个地图 CityMap 及它的 行长度 n 和 列长度 m ,其中1代表经理位置, 2 代表商家位置, -1 代表不能经过的地区, 0 代表可以经过的地区,请返回方案数,保证一定存在合法路径。保证矩阵的长宽都小于等于 10。
注意:需保证所有方案的距离都是最短的方案
数据范围: 2 ≤ n , m ≤ 10 2 \leq n,m \leq 10 2≤n,m≤10
例如当输入为[[2,0,0,0],[0,-1,-1,0],[0,-1,1,0],[0,0,0,0]],4,4时,对应的4行4列CityMap如下图所示:
经理的位置在(2,2),商家的位置在(0,0),经分析,经理到达商家地址的最短方案有两种,分别为:
(2,2)->(2,3)->(1,3)->(0,3)->(0,2)->(0,1)->(0,0)
和
(2,2)->(3,2)->(3,1)->(3,0)->(2,0)->(1,0)->(0,0),所以对应的返回值为2
示例1
输入:
[[0,1,0],[2,0,0]],2,3
返回值:
2
示例2
输入:
[[2,0,0,0],[0,-1,-1,0],[0,-1,1,0],[0,0,0,0]],4,4
返回值:
2
- 原题链接
- 算法标签
- 动态规划
- BFS
BFS
-
BFS可以进行最短路的搜索,这题在此基础上稍微进行了改动
-
遍历过得节点标记 − 1 -1 −1防止重复遍历,但是对于中点不需要标记,否则第二次到达无法辨识是终点
-
用
min_dis
记录最短的距离,min_cnt
记录有多少条最短路 -
结构体
TII
定义了地图点坐标以及从起点到达该点的距离,其邻接节点在其基础上+1 -
注意下一个节点的位置要判断是否越界
#include <bits/stdc++.h>
#define debug
#define x first
#define y second
using namespace std;
struct TII {
int x, y, dis;
};
int countPath(vector<vector<int> > &CityMap, int n, int m) {
queue<TII> q;
int dx[] = {0, -1, 0, 1}, dy[] = {-1, 0, 1, 0};
//找起点
TII st;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (CityMap[i][j] == 1) {
st = {i, j, 0};
break;
}
}
}
//BFS搜索
q.push(st);
CityMap[st.x][st.y] = -1;
int min_dis = 0x3f3f3f3f;
int min_cnt = 0;
while (!q.empty()) {
TII tmp = q.front();
q.pop();
cout << tmp.x << ' ' << tmp.y << endl;
if (CityMap[tmp.x][tmp.y] == 2) {
if (tmp.dis < min_dis) {
min_cnt = 1;
min_dis = tmp.dis;
} else if (tmp.dis == min_dis) { min_cnt++; }
} else {
CityMap[tmp.x][tmp.y] = -1;//标记已经走过,终点不能标记,否则第二次到达无法判断
//将邻接的点加入队列
for (int i = 0; i < 4; ++i) {
int xi = tmp.x + dx[i], yi = tmp.y + dy[i];
if (xi < 0 || xi >= n || yi < 0 | yi >= m)continue;
if (CityMap[xi][yi] != -1) {
q.push({xi, yi, tmp.dis + 1});
}
}
}
}
return min_cnt;
}
int main() {
#ifdef debug
freopen("in.txt", "r", stdin);
#endif
ios::sync_with_stdio(0);
int n, m;
cin >> n >> m;
vector<vector<int>> g(n, vector<int>(m));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> g[i][j];
}
}
cout << '@' << countPath(g, n, m) << endl;
return 0;
}