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;
}
posted @ 2025-12-17 13:49  To_Carpe_Diem  阅读(3)  评论(0)    收藏  举报