UVA11573 Ocean Currents

题目传送门

分析

无边权,最短路,一眼BFS。
两种情况。
1.随波逐流。不消耗能量,代价为 0 0 0
2.逆流而上。随意移动到相邻格子,消耗能量,代价为 1 1 1
出现了不同的代价,如何处理?
BFS的一个重要性质,当边权固定时,一个点第一次被遍历到的代价为最小,也就是说保证队列的队头是队列中最小的。
这是什么?
优先队列
其实当只有两种权值时,双端队列的效果类似,但是优先队列更具有普遍性。
所以,可以将BFS中的普通队列改为优先队列,然后分成上述两种情况搜索,问题解决。

#include<bits/stdc++.h>
#define endl putchar('\n')
using namespace std;
const int M=1e3+5;
void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x<10){putchar(x+'0');return;}
	print(x/10);
	putchar(x%10+'0');
}
int n,m;
int T;
int a[M][M];
int x,y,r,c;
struct node{
	int x,y,dis;
	bool friend operator<(node a,node b){
		return a.dis>b.dis;
	}
};
int vis[M][M];
int dis[M][M];
int dx[8]={-1,-1,0,1,1,1,0,-1};
int dy[8]={0,1,1,1,0,-1,-1,-1};
void bfs(){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			vis[i][j]=0;
		}
	}
	priority_queue<node>q;
	q.push(node{x,y,0});
	vis[x][y]=1;
	dis[x][y]=0;
	while(!q.empty()){
		node p=q.top();
		q.pop();
		if(p.x==r&&p.y==c){
			print(p.dis);
			return;
		}
		for(int i=0;i<8;i++){
			int xx=p.x+dx[i];
			int yy=p.y+dy[i];
			if(xx<1||yy<1||xx>n||yy>m||(vis[xx][yy]&&dis[xx][yy]<=p.dis+1))continue;
			dis[xx][yy]=p.dis+1;
			vis[xx][yy]=1;
			q.push(node{xx,yy,p.dis+1});
		}
		int imsb=a[p.x][p.y];
		int xx=p.x+dx[imsb];
		int yy=p.y+dy[imsb];
		if(xx<1||yy<1||xx>n||yy>m||(vis[xx][yy]&&dis[xx][yy]<=p.dis))continue;
		dis[xx][yy]=p.dis;
		q.push(node{xx,yy,p.dis});
	}
}
signed main(){
	ios::sync_with_stdio(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char w;
			cin>>w;
			a[i][j]=w-'0';
		}
	}
	cin>>T;
	while(T--){
		cin>>x>>y>>r>>c;
		bfs();
		endl;
	}
}
posted on 2025-07-02 18:20  fish2012  阅读(6)  评论(0)    收藏  举报  来源