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求解。

猜你喜欢

转载自www.cnblogs.com/bianjunting/p/11107990.html