zoukankan      html  css  js  c++  java
  • 中国计量大学现代科技学院第四届“中竞杯”程序设计校赛 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
    ", 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
    ");
    }
    
    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;
    }
    
  • 相关阅读:
    HDU 2081 手机短号
    HDU 2053 Switch Game
    HDU 2040 亲和数
    HDU 2070 Fibbonacci Number
    redis集群安装2
    redis集群1
    批量更新sql
    centos 6升级 GCC 到4.8
    排序4 -- 插入排序
    排序3--选择排序
  • 原文地址:https://www.cnblogs.com/tuchen/p/14092230.html
Copyright © 2011-2022 走看看