中国计量大学现代科技学院第四届“中竞杯”程序设计校赛 I 题 (双端队列bfs / 优先队列bfs)

题目链接:https://ac.nowcoder.com/acm/contest/9680/I

记录一下上次移动的方向,如果这次移动的方向和上次相同,那么边权为 \(0\), 否则边权为 \(1\)
边权仅为 \(0/1\) 的图求最短路径可以使用双端队列 \(bfs\),如果边权为 \(0\) 就加入队首,否则加入队尾,
这样可以保证队列中距离的二段性和单调性,使得第一次到达目标状态时即为最优答案

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 5010;

int n, m; 
int sx, sy, ex, ey;
int a[maxn][maxn];
int dis[maxn][maxn];
char s[maxn];

int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};

struct Node{
	int x, y, step, dir;
};

deque<Node> q;

void bfs(){
	memset(dis, 0x3f, sizeof(dis));
	Node start;
	start.x = sx, start.y = sy; start.step = 0; start.dir = -1;
	dis[sx][sy] = 0;
	q.push_front(start);
	
	while(!q.empty()){
		Node u = q.front(); q.pop_front();
		
		if(u.x == ex && u.y == ey){
			printf("%d\n", u.step);
			return;
		}
		
                if(u.step > dis[u.x][u.y]) continue; // 之前放入队列的状态已经被更新过了,当前状态无用,队列中后面相同状态的更小的dis来更新

		for(int i = 0 ; i < 4 ; ++i){
			int x = u.x + dx[i], y = u.y + dy[i];
			
			if(x > 0 && x <= n && y > 0 && y <= m && a[x][y] != 1){
				Node now;
				now.x = x, now.y = y, now.dir = i;
				if(i != u.dir && u.dir != -1){
					now.step = u.step + 1;
					if(dis[x][y] > now.step){ // 一定要加 $dis$ 的限制,更优的状态才可以被更新,否则会超限
						dis[x][y] = now.step;
						q.push_back(now);
					}
				} else{
					now.step = u.step;
					if(dis[x][y] > now.step){
						dis[x][y] = now.step;
						q.push_front(now);
					}					
				}
			}
		}
	}
	
	printf("-1\n");
}

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	n = read(), m = read();
	sx = read(), sy = read(), ex = read(), ey = read();
	++sx, ++sy, ++ex, ++ey;
	
	for(int i = 1 ; i <= n ; ++i){
		scanf("%s", s + 1);
		for(int j = 1 ; j <= m ; ++j){
			a[i][j] = s[j] - '0';
		}
	}
	
	bfs();
	
	return 0;
}
posted @ 2020-12-06 11:37  Tartarus_li  阅读(134)  评论(0编辑  收藏  举报