去年因为太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求解。