• SUSTOJ_路痴的单身小涵(图中最短路的条数)


      去年因为太low没有做出来校赛的最后一题,遂今年校赛做了这个题,下面我做详细描述。

    原题链接

      本题大意:给定一个无向图G,每个边的权值为1,图中L表示起点,C表示终点,#表示未通路,给定时间k,让你判断是否能在给定时间k内走到C,并回答路径最短的路径有多少条?

      本题思路:裸的搜索问题,由于图过大,所以直接dfs搜会超时,需要先bfs求解答案如果k步内能走到则再进行下一步的求解。。。

    参考代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <stack>
    #include <set>
    #include <map>
    #include <cmath>
    #include <algorithm>
    #define mid ((l + r) / 2)
    using namespace std;
    
    typedef pair<int, int> pii;
    typedef long long ll;
    typedef unsigned long long ull;
    const double pi = acos(-1.0);
    
    const int maxn = 1e3 + 5;
    int n, m, k, step, ans, Dist;
    char G[maxn][maxn];
    int dist[maxn][maxn];
    bool vis[maxn][maxn];
    pii B, E, now, Next;
    
    int bfs(int x, int y) {
        memset(vis, false, sizeof vis);
        memset(dist, 0, sizeof dist);
        queue <pii> Q;
        Q.push(make_pair(x, y));
        dist[x][y] = 0;
        while(!Q.empty()) {
            pii now = Q.front();
            Q.pop();
            if(now.first == E.first && now.second == E.second) return dist[now.first][now.second];
            for(int dx = -1; dx <= 1; dx ++) {
                for(int dy = -1; dy <= 1; dy ++) {
                    if(abs(dx - dy) == 1) {
                        Next.first = now.first + dx;
                        Next.second = now.second + dy;
                        if(!vis[Next.first][Next.second] && Next.first >= 0 && Next.first < n && Next.second >= 0 && Next.second < m && G[Next.first][Next.second] != '#') {
                            dist[Next.first][Next.second] = dist[now.first][now.second] + 1;
                            Q.push(make_pair(Next.first, Next.second));
                            vis[Next.first][Next.second] = true;
                        }
                    }
                }
            }
        }
        return -1;
    }
    
    void dfs(pii B, pii E, int D) {
        if(B.first == E.first && B.second == E.second) {
            if(D < Dist) {
                step = 1;
                Dist = D;
            } else if(D == Dist) step ++;
            return;
        }
        if(D > Dist) return;
        for(int i = -1; i <= 1; i ++) {
            for(int j = -1; j <= 1; j ++) {
                if(abs(i - j) == 1) {
                    if(B.first + i >= 0 && B.first + i < n && B.second + j >= 0 && B.second + j < m) {
                        if(G[B.first + i][B.second + j] != '#' && !vis[B.first + i][B.second + j]) {
                            vis[B.first + i][B.second + j] = true;
                            dfs(make_pair(B.first + i, B.second + j), E, D + 1);
                            vis[B.first + i][B.second + j] = false;
                        }
                    }
                }
            }
        }
    }
    
    int main() {
        ios_base :: sync_with_stdio(false);
        int t, Case = 0;
        cin >> t;
        while(t --) {
            step = 0;
            Dist = 0x3f3f3f3f;
            cin >> n >> m >> k;
            for(int i = 0; i < n; i ++) cin >> G[i];
            for(int i = 0; i < n; i ++) {
                for(int j = 0; j < m; j ++) {
                    if(G[i][j] == 'L') B = make_pair(i, j);
                    if(G[i][j] == 'C') E = make_pair(i, j);
                }
            }
            ans = bfs(B.first, B.second);
            if(ans > k) ans = -1;
            cout << "Case #" << ++ Case << ": " << ans << ' ';
            if(ans != -1) {
                memset(vis, false, sizeof vis);
                dfs(B, E, 0);
                cout << step;
            }
            cout << endl;
        }
        return 0;
    }

       相同的题目,如果边的权值不为1,则可用SPFA+dfs求解。

  • 相关阅读:
    守护进程(Daemon)
    Socket select的用法
    被误解的C++——磨刀不误砍柴工
    C++ 虚函数表解析
    进程间通信IPC
    pthread_join函数及linux线程
    详细讲解C++ 类的继承
    Trilogy公司的笔试题
    linux下fork的使用
    Ruby 编程规范
  • 原文地址:https://www.cnblogs.com/bianjunting/p/11107990.html
Copyright © 2020-2023  润新知