迷宫问题 —— 最短路径条数

    求迷宫的最短路径条数有多少条,一般方法会超时,这里记录一下模板

    简要思路:用 a n s ans ans记录到每个点的条数,当新到达的点的新距离小于就旧的距离时,更新新点的 a n s ans ans;若新距离等于旧距离,也就是可能是最短路径的时候,就 a n s 新 + = a n s 旧 ans_{新} += ans_{旧} ans+=ans

     P S : PS: PS若新旧距离相等,则不需要再将该点加入到队列中,因为这个点已经在队列里了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f; 
const ll mod = 1000000007;
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};

int r, c, edx, edy;
int dis[505][505], maze[505][505];
char mp[505][505];
ll ans[505][505];
bool vis[505][505];

struct Point {
    int x, y, t;
    bool operator<(const Point & b) const {
        return t>b.t; 
    }
    Point(){}
    Point(int x,int y,int t):x(x),y(y),t(t) {}
} p;

void BFS() {
    dis[1][1] = 0;
    ans[1][1] = 1;
    priority_queue <Point> pq;
    pq.push(Point(1,1,0));
    
    while(!pq.empty()) {
        int nx, ny;
        //找点 
        Point cur = pq.top(); pq.pop();
        if(vis[cur.x][cur.y] == 1) continue;
        vis[cur.x][cur.y] = 1;
        for(int k=0; k<4; k++) {
            nx = cur.x + dx[k];
            ny = cur.y + dy[k];
            if(vis[nx][ny] == 1) continue;
            if(nx<1 || nx>r || ny<1 || ny>c) continue;
            int t = dis[cur.x][cur.y] + maze[nx][ny];
            if(dis[nx][ny] > t) {
                dis[nx][ny] = t;
                ans[nx][ny] = ans[cur.x][cur.y]%mod;
                pq.push(Point(nx, ny, dis[nx][ny]));
            }
            else if(dis[nx][ny] == t) {
                ans[nx][ny] += ans[cur.x][cur.y];
                ans[nx][ny] %= mod;
                //pq.push(Point(nx, ny, dis[nx][ny]));
            }         
        }
    }
    if(dis[edx][edy] == INF) printf("-1\n");
    else printf("%lld\n", ans[edx][edy]%mod);
} 
 
void init() {
    memset(vis,0,sizeof(vis));
    memset(ans,0,sizeof ans);
    memset(maze,INF,sizeof(maze));
    memset(dis,INF,sizeof(dis));
}

int main(){
    int cas;
    scanf("%d", &cas); 
    while(cas--) {
        scanf("%d%d", &r, &c); 
        init();
        for(int i=1; i<=r; i++) 
            scanf("%s", mp[i]+1);
        for(int i=1; i<=r; i++) 
            for(int j=1; j<=c; j++) 
                if(mp[i][j] == '.') 
					maze[i][j] = 1;
        
        scanf("%d%d", &edx, &edy);
        BFS() ;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值