P5195 [USACO05DEC] Knights of Ni S
P5195 [USACO05DEC] Knights of Ni S
大意
从起点走到终点,中间经历一个灌木,求最短路。
思路
这个题的话,题目描述不是很清楚,其实只有一个终点,因此,我们只需要解决的问题是求 \(\min(s \to k_i \to t), k_i\) 表示灌木丛,但是 \(W, H \le 1000\),我们如果直接搜索 \(s\) 到每个灌木的距离,再从每个灌木向终点 \(t\) 去搜索显然会炸,因为灌木的个数一多就直接爆 \(1e7\) 了。
由于起点和终点具有唯一性,所以我们是不是直接去从搜索 \(s \to k_i\) 的最短路,和 \(t \to k_i\) 的最短路,这样的话,只需要在每一个 \(k_i\) 的位置进行匹配,然后取 \(\min(s \to k_i + k_i \to t)\) 即可,类似双向搜索。
代码
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
const int MAXN = 1005;
const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};
int W, H, sx = 0, sy = 0, ex = 0, ey = 0;
char mp[MAXN][MAXN];
bool vis1[MAXN][MAXN], vis2[MAXN][MAXN];
int d1[MAXN][MAXN], d2[MAXN][MAXN];
vector<pair<int, int> > p;
void bfs1(int x, int y){//起点 -> 灌木
queue<pair<int, int> > q;
d1[x][y] = 0;
vis1[x][y] = 1;
q.push(make_pair(x, y));
while(!q.empty()){
int xx = q.front().first, yy = q.front().second; q.pop();
for(int i = 0;i < 4;i ++){
int nx = xx + dx[i];
int ny = yy + dy[i];
if(vis1[nx][ny] || mp[nx][ny] == '1') continue;
if(nx < 1 || ny < 1 || nx > W || ny > H) continue;
d1[nx][ny] = d1[xx][yy] + 1;
vis1[nx][ny] = 1;
q.push(make_pair(nx, ny));
}
}
}
void bfs2(int x, int y){//终点 -> 灌木
queue<pair<int, int> > q;
d2[x][y] = 0;
vis2[x][y] = 1;
q.push(make_pair(x, y));
while(!q.empty()){
int xx = q.front().first, yy = q.front().second; q.pop();
for(int i = 0;i < 4;i ++){
int nx = xx + dx[i];
int ny = yy + dy[i];
if(vis2[nx][ny] || mp[nx][ny] == '1') continue;
if(nx < 1 || ny < 1 || nx > W || ny > H) continue;
d2[nx][ny] = d2[xx][yy] + 1;
vis2[nx][ny] = 1;
q.push(make_pair(nx, ny));
}
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
memset(d1, 0x3f3f3f3f, sizeof(d1));
memset(d2, 0x3f3f3f3f, sizeof(d2));
cin >> H >> W;
for(int i = 1;i <= W;i ++){
for(int j = 1;j <= H;j ++){
cin >> mp[i][j];
if(mp[i][j] == '2'){
sx = i, sy = j;
}
else if(mp[i][j] == '3'){
ex = i, ey = j;
}
else if(mp[i][j] == '4'){
p.push_back(make_pair(i, j));
}
}
}
bfs1(sx, sy);
bfs2(ex, ey);
// for(int i = 1;i <= W;i ++){
// for(int j = 1;j <= H;j ++){
// cout << d1[i][j] << ' ';
// }
// cout << '\n';
// }
// cout << '\n';
// for(int i = 1;i <= W;i ++){
// for(int j = 1;j <= H;j ++){
// cout << d2[i][j] << ' ';
// }
// cout << '\n';
// }
int ans = 1e9;
for(auto now : p){
int x = now.first, y = now.second;
ans = min(d1[x][y] + d2[x][y], ans);
}
cout << ans << '\n';
return 0;
}
本文来自一名高中生,作者:To_Carpe_Diem

浙公网安备 33010602011771号