用一个整形矩阵matrix表示一个网格,1代表有路,0代表无路,每一个位置只要不越界,都有上下左右四个方向,求从最左上角到右下角的最短通路值
例如,matrix为:
1 0 1 1 1
1 0 1 0 1
1 1 1 0 1
0 0 0 0 1
通路只有一条,由12个1构成,所以返回12
[要求]
时间复杂度为,空间复杂度为
第一行两个整数N,M表示矩形的长宽
接下来N行,每行一个长度为M的字符串表示矩形
输出一个整数表示最小步数
若从(1, 1)无法到达(n, m)请输出-1
4 5 10111 10101 11101 00001
12
4 5 11011 11111 11111 00001
8
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.Queue; import java.util.LinkedList; public class Main { static int[] dx = new int[]{1, -1, 0, 0}; static int[] dy = new int[]{0, 0, 1, -1}; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] params = br.readLine().split(" "); int n = Integer.parseInt(params[0]), m = Integer.parseInt(params[1]); Queue<int[]> queue = new LinkedList<>(); char[][] grid = new char[n][m]; boolean[][] visited = new boolean[n][m]; for(int i = 0; i < n; i++){ grid[i] = br.readLine().toCharArray(); if(grid[0][0] == '0'){ System.out.println(-1); return; } } queue.offer(new int[]{0, 0}); int steps = 0; loop: while(!queue.isEmpty()){ steps ++; int queueSize = queue.size(); // 下一步要走的位置都在队列中 for(int k = 0; k < queueSize; k++){ int[] pos = queue.poll(); if(pos[0] == n - 1 && pos[1] == m - 1) break loop; // 到达终点,退出BFS visited[pos[0]][pos[1]] = true; // 四个方向走动 for(int i = 0; i < 4; i++){ int x = pos[0] + dx[i]; int y = pos[1] + dy[i]; if(0 <= x && x < n && 0 <= y && y < m && grid[x][y] == '1' && !visited[x][y]) queue.offer(new int[]{x, y}); } } } System.out.println(steps == 0? -1: steps); } }但是这个题吧,有点醉,一模一样的思路Java会超时,C++就给我过了
# include <bits/stdc++.h> using namespace std; vector<int> dx = {-1, 1, 0, 0}; vector<int> dy = {0, 0, 1, -1}; int BFS(int n, int m, vector<vector<char>> grid){ bool visited[n][m]; memset(visited, false, sizeof(visited)); queue<vector<int>> q; q.push(vector<int>(2)); int steps = 0; while(!q.empty()){ steps ++; int queueSize = q.size(); for(int k = 0; k < queueSize; k++){ vector<int> cur = q.front(); q.pop(); if(cur[0] == n - 1 && cur[1] == m - 1) return steps; for(int i = 0; i < 4; i++){ int x = cur[0] + dx[i]; int y = cur[1] + dy[i]; if(0 <= x && x < n && 0 <= y && y < m && grid[x][y] == '1' && !visited[x][y]){ q.push({x, y}); visited[x][y] = true; } } } } return -1; } int main(){ int n,m; cin >> n >> m; vector<vector<char>> grid(n, vector<char>(m)); for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++) cin >> grid[i][j]; } cout << BFS(n, m, grid) << endl; return 0; }
//注:该代码,N和M与题目中的顺序相反 #include<iostream> #include<vector> using namespace std; typedef struct//节点 { int x; int y; }node; int dx[4] = { 1,-1,0,0 };//用于判断上下左右时使用 int dy[4] = { 0,0,1,-1 };//同上 int main() { int M, N; cin >> M >> N; vector<vector<char>> m(M);//用于储存矩阵 vector<vector<int>> num(M);//用于储存走到矩阵各点的距离 for (int x = 0; x < M; x++)//扩容 { m[x].resize(N); num[x].resize(N); } for (int x = 0; x < M; x++)//输入矩阵元素 { getchar(); for (int y = 0; y < N; y++) { scanf("%c", &m[x][y]); } } num[0][0] = 1;//走到0,0坐标默认为1 m[0][0] = '0';//将0,0坐标的元素变'0',以免再次被查找 int flag = 1;//用于判断是否走到了右下角的点 node t = { 0,0 }; vector<node>q;//用于保存路上走到的点的坐标 q.push_back(t);//将0,0点存到路径动态数组 while (q.size())//当数组中没有元素时代表没路可走,即停止 { t = q[0];//保存第一个点,以此点开始查找周围 q.erase(q.begin());//将第一个点从数组中去除,以免下次被调用 if (t.x == M - 1 && t.y == N - 1)//如果当前的点是右下角的点,就直接输出当前num矩阵中该点的数即可,第一次走到定为最小 { flag = 0;//将flag变0,代表已走到 cout << num[M - 1][N - 1]; break; } for (int i = 0; i < 4; i++)//上下左右查找为'1'的点 { int _x = t.x + dx[i]; int _y = t.y + dy[i]; if (_x < 0 || _x >= M || _y < 0 || _y >= N)//坐标越界跳过,执行下一次循环 { continue; } if (m[_x][_y] == '1')//找到为'1'的点 { m[_x][_y] = '0';//将该点变为'0'防止下次被查找 num[_x][_y] = num[t.x][t.y] + 1;//令该点对应的num的数变为前一个点的+1 node new_t = { _x,_y }; q.push_back(new_t);//因为该坐标可走,所以将新的坐标保存到数组中,做下次查找 } } } if (flag)//如果找到右下角得点,不能输出,反之输出-1 { cout << -1; } return 0; }
#include <bits/stdc++.h> using namespace std; char G[1001][1001]; int dir[4][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}}; struct P{ int x, y, t; }; int BFS(int n, int m){ bool vis[n+1][m+1]; memset(vis, false, sizeof(vis)); vis[1][1] = true; queue<P> q; q.push(P{1,1,1}); while(!q.empty()){ P p = q.front(); q.pop(); if(p.x==n && p.y==m) return p.t; for(int i=0;i<4;i++){ int xx = p.x + dir[i][0]; int yy = p.y + dir[i][1]; int tt = p.t + 1; if(xx>=1 && xx<=n && yy>=1 && yy<=m && G[xx][yy]=='1' && !vis[xx][yy]){ q.push(P{xx, yy, tt}); vis[xx][yy] = true; } } } return -1; } int main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>G[i][j]; cout<<BFS(n,m)<<endl; return 0; }
#include <bits/stdc++.h> using namespace std; // 一定要用char int bfs(vector<vector<char>>& matrix, int n, int m){ queue<pair<int, int>> qu; qu.push({1, 1}); int res = 0; while(!qu.empty()){ int size = qu.size(); res++; while(size--){ auto cur = qu.front(); qu.pop(); int x = cur.first, y = cur.second; if(x == n && y == m){ return res; } if(x - 1 >= 1 && matrix[x - 1][y] == '1'){ matrix[x - 1][y] = '0'; qu.push({x - 1, y}); } if(x + 1 <= n && matrix[x + 1][y] == '1'){ matrix[x + 1][y] = '0'; qu.push({x + 1, y}); } if(y - 1 >= 1 && matrix[x][y - 1] == '1'){ matrix[x][y - 1] = '0'; qu.push({x, y - 1}); } if(y + 1 <= m && matrix[x][y + 1] == '1'){ matrix[x][y + 1] = '0'; qu.push({x, y + 1}); } } } return -1; } int main() { int n, m; cin >> n >> m; // 用 char 作为输入 vector<vector<char>> matrix(n + 1, vector<char>(m + 1)); for(int i = 1; i <= n; ++i){ for(int j = 1; j <= m; ++j){ cin >> matrix[i][j]; } } cout << bfs(matrix, n, m); return 0; }
#include <stdio.h> #include <stdlib.h> #define not ! typedef struct Coordintate { int x; int y; } Coord; // function prototype void printGrid(int* *grid, const int kRows, const int kCols); int breadth_first_search_algorithm(int* *grid, const int kRows, const int kCols); int main(const int argc, const char* const argv[]) { int m, n; fscanf(stdin, "%d %d\n", &m, &n); int grid[m][n]; // 逻辑上两维的, 但在内存布局中二维数组是按一维线性连续存储的。 int x, y; char str[n + 1]; for (y = 0; y < m ; ++y) { gets(str); for (x = 0; x < n; ++x) *(*(grid + y) + x) = *(str + x) - 48; } int* rows_of_grid[m]; // 行指针 for (y = 0; y < m; ++y) *(rows_of_grid + y) = grid + y; // printGrid(rows_of_grid, m, n); fprintf(stdout, "%d", breadth_first_search_algorithm(rows_of_grid, m, n)); return 0; } int breadth_first_search_algorithm(int* *grid, const int kRows, const int kCols) { Coord q[kRows * kCols]; // 队列的大小由算法的时简复杂度决定,每个单位格最多入队出队一次! int front = 0, rear = 0; *(q + rear++) = (Coord) {.x = 0, .y = 0}; **grid = 0; // mark as visited static const int dirs[] = { 0, -1, 0, 1, 0 }; Coord coord; int i, x, y, nx, ny, steps = 0; while (front < rear) { size_t s = rear - front; while (s--) { coord = *(q + front++); x = coord.x, y = coord.y; if (x == kCols - 1 && y == kRows - 1) return steps + 1; for (i = 0; i < 4; ++i) { nx = x + *(dirs + i), ny = y + *(dirs + i + 1); if (nx < 0 || ny < 0 || nx == kCols || ny == kRows || !*(*(grid + ny) + nx)) continue; *(q + rear++) = (Coord) {.x = nx, .y = ny}; *(*(grid + ny) + nx) = 0; // mark as visited } } ++steps; } return -1; } void printGrid(int* *grid, const int kRows, const int kCols) { int x, y; for (y = 0; y < kRows; ++y) { for (x = 0; x < kCols; ++x) printf("%d ", *(*(grid + y) + x)); fputc(10, stdout); } }
Java BFS
import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; public class Main { private static int m ; private static int n ; private static int[][] mat; public static void main(String[] args) { int[][] direcion = {{1,0},{0,1},{-1,0},{0,-1}}; int res = - 1; Scanner sc = new Scanner(System.in); m = sc.nextInt(); n = sc.nextInt(); mat = new int[m][n]; for (int i = 0; i < m; i++) { String s = sc.next(); for (int j = 0; j < n; j++) { mat[i][j] = s.charAt(j) -'0'; } } Queue<Node> queue = new LinkedList<>(); Node root = new Node(0,0,1); queue.offer(root); while(!queue.isEmpty()){ Node p = queue.peek(); int x = p.x; int y = p.y; int dis = p.dis; if(x == m-1 && y == n - 1){ res = dis; break; } for (int i = 0; i < direcion.length; i++) { int newX = direcion[i][0] + x; int newY = direcion[i][1] + y; Node temp = new Node(newX,newY,dis+1); if(isTrue(temp)){ queue.offer(temp); mat[newX][newY] = 0; } } queue.poll(); } System.out.println(res); } public static class Node{ private int x; private int y; private int dis; public Node(int x, int y, int dis) { this.x = x; this.y = y; this.dis = dis; } } public static boolean isTrue(Node node){ int x = node.x; int y = node.y; if((x<0 || x>=m)||(y<0 || y>=n)) return false; if(mat[x][y] == 0) return false; return true; } }
# -*- coding: utf-8 -*- # !/usr/bin/python3 # 解题思路,利用广度优先搜索(BFS)进行遍历,从00到mn位置最少需要几层,就是最短路径的长度 # 判断每层的条件:下标合法不越界,数组中值为1,并且没有被遍历过 # BFS将每层可遍历的元素保存到一个集合中,将该集合作为下次遍历的对象,寻找下一层 # 只到找到mn位置为止,如果找不到就是-1 def bfs(arr, m, n): if arr[0][0] == 0: return -1 vst = [[0 for k in range(n)] for k in range(m)] qe, steps, vst[0][0] = {(0, 0)}, 1, 1 while qe: tmp = set() for x, y in qe: if (x, y) == (m - 1, n - 1): return steps for k, l in ((x - 1, y), (x, y + 1), (x + 1, y), (x, y - 1)): if 0 <= k < m and 0 <= l < n and arr[k][l] == 1 and vst[k][l] == 0: tmp.add((k, l)) vst[k][l] = 1 steps += 1 qe = tmp return -1 while True: try: m, n = map(int, input().split()) arr = [] for i in range(m): s = input() tmp = [] for j in range(n): tmp.append(int(s[j])) arr.append(tmp) print(bfs(arr, m, n)) except: break