迷宫 (统计最短路径的条数)

题目描述:
现有一个30行 x 50列的迷宫,0表示空地,1表示障碍,你可以从第一行的任意位置(非1)出发,到达最后一行的任意位置(非1)就算通过迷宫,要求最短路径的条数

迷宫:

01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000

思路: 直接bfs,把第一行的所有非1点加入队列,队列出口就是扫到横坐标是29的最后一行(非1)。记下当前的最短路径和这个长度的路径条数,由于bfs的特性,一旦出现step比记录的最短路径大,后面的也一定都大,可以return,输出cnt
注意: 这题有个坑,请看如下迷宫:

11011
10001
10101
10001
11011

这个图明显看出来左右两边到(5, 2)的路径一样,也就是答案应该是2,但是由于bfs时第一次到(4, 2)时把vis标记为true了,就导致第二次下不来了

改进: 把vis开成int数组,刚开始初始化为-1,走过就标记为到那个点的所用step,这样一来,在刚刚的(4, 2)点时,由于vis里的step和第二次到达时计算出的step一样,就仍然可以走过去。看注释!
Code:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<queue>
#include<algorithm>
#define ll long long
using namespace std;

int cnt = 0;
int min_len = 2000;
char mp[100][100];
int vis[100][100];
//vis刚开始全部初始化为-1,走过了就标记为走到当前点所花step,如果下一个点所花step小于等于这个点的vis,证明可能会出现更优解,此时也可以走(虽然之前已经从这个点走过了)
int n=30, m=50;
int dx[]={
    
    1,0,-1,0};
int dy[]={
    
    0,-1,0,1};
struct node {
    
    
    int x, y;
    int step;
};
queue<node> q;
inline bool is_in(int x, int y) {
    
    
    return x>=0&&x<n&&y>=0&&y<m;
}
void bfs() {
    
    
    node t;
    t.x = 0;
    t.step = 0;
    for (int i=0;i<m;i++) {
    
    
        if (mp[0][i] == '0') {
    
    
            t.y = i;
            vis[0][i] = 0;
            q.push(t);
        }
        
    }

    while (!q.empty()) {
    
    
        node nd = q.front();q.pop();
        
        for (int i=0;i<4;i++) {
    
    
            int nextx = nd.x + dx[i], nexty = nd.y + dy[i];
            //vis[][]==-1: 没走过, vis[][]==nd.step+1: 下一次可能出现更优解
            if (is_in(nextx, nexty) && (vis[nextx][nexty] == -1 || vis[nextx][nexty] >= nd.step + 1) && mp[nextx][nexty] == '0') {
    
    
                t.x = nextx;
                t.y = nexty;
                t.step = nd.step + 1;//nd.step+1是到下个点所花step
                q.push(t);
                vis[nextx][nexty] = nd.step + 1;
                if (nextx==n-1) {
    
    
                    if (nd.step+1 > min_len) {
    
    //因为bfs的特性,一旦出现比min_len大的情况,后面的情况一定都比min_len大,故此时cnt就是答案
                        return;
                    }
                    min_len = nd.step + 1;
                    cnt++;
                    
                }
            }
        }
    }
}

int main()
{
    
    
    freopen("in.txt", "r", stdin);//把地图放在名为"in.txt"的文件里了,freopen()可以重定向输入流
    memset(vis, -1, sizeof(vis));
    for (int i=0;i<n;i++) {
    
    
        cin>>mp[i];
    }
    bfs();
    cout<<cnt<<endl;
    return 0;
}

总结: 我之前写错的原因是因为搜索时的状态没标识好,由于不是仅仅搜索最短路径长度,只保存是否访问过时无法判断该不该走这个点的

猜你喜欢

转载自blog.csdn.net/u010017231/article/details/104622806