zoukankan      html  css  js  c++  java
  • 九校联考-长沙市一中NOIP模拟Day2T2 走格子(cell)

    问题描述

    CYJ想找到他的小伙伴FPJ,.CYJ和FPJ现在位于一个房间里,这个房间的布置可以看成一个N行M列的矩阵,矩阵内的每一个元素会是下列情况中的一种:

    1. 障碍区域—这里有一堵墙(用‘#’表示).
    2. 这是CYJ最开始在的区域(用‘C’表示).
    3. 这是FPJ在的区域(用‘F’表示).
    4. 空区域(用‘.’表示).
      CYJ携带了一个所谓传送枪的东西,这是一把可以创造传送门的枪械,在每一次行动中,他可以选择下列操作中的一项:
    5. 移向一个相邻的格子中(上,下,左,右,不能移到墙在的格子里).这个操作要消耗一个单位的时间.
    6. 转向一个墙(不需要相邻,只需面向即可),向其发射传送门,传送门会留在墙内面向你的地方(至多只能同时存在两扇传送门),若墙上已经有两扇传送门,而你发射了第三扇,那么最初发射的那一扇会消失。同时,你无法在一个位置制造两扇传送门(这个操作不会耗费时间)。
    7. 如果他与一块墙壁相邻且面前有一扇传送门,那么他可以移动到另一扇传送门前方的格子。这个操作会耗费一个单位的时间.
      CYJ想要知道自己最少需要多少时间才能够从起点(‘C’)到达终点(‘F’).
      请注意:我们保证地图边缘会是一圈墙壁且一定存在‘C’,‘F’.

    输入

    第一行输入两个正整数 N 和 M ,(4 ≤ N,M ≤ 500).表示地图大小。
    接下来的N行每行一个长度为M的字符串.表示地形。

    输出

    你需要输出最少的到达终点的时间,如果不能到达请输出”no”。

    先BFS搜出每个点到墙(或到旁边有墙的点)的距离,同时用这个距离建图,建完图跑diji或spfa得出正解

    #include<bits/stdc++.h>
    using namespace std;
    
    const int Maxn = 505;
    const int MX = 3e5+5; 
    const int inf = 1e9;
    
    int N,M,S,T,cnt;
    int md[Maxn][Maxn],Lm[Maxn][Maxn],Rm[Maxn][Maxn];
    int Dm[Maxn][Maxn],Um[Maxn][Maxn],hed[MX];
    int nxt[MX<<4],to[MX<<4],len[MX<<4],dis[MX];
    char mp[Maxn][Maxn]; 
    struct  data{
    	int x , y;
    	bool operator <(const data &A) const{
    		return y > A.y;
    	}
    };
     
    queue<data>Q;
     
    inline int id(int x,int y){return (x - 1)*M + y;}
    
    void inc(int x,int y,int d){
    	if(mp[x][y] == '.' && !md[x][y])
    		md[x][y] = d , Q.push((data){x,y});	
    }
    
    void Bfs(){
    	while(!Q.empty()){
    		int x = Q.front().x,y = Q.front().y;
    		Q.pop();
    		inc(x - 1 , y , md[x][y] + 1);
    		inc(x , y - 1 , md[x][y] + 1);
    		inc(x + 1 , y , md[x][y] + 1);
    		inc(x , y + 1 , md[x][y] + 1); 
    	}
    }
    
    void Adg(int x,int y,int l){
    	nxt[++cnt] = hed[x]; to[cnt] = y; 
    	hed[x] = cnt; len[cnt] = l; 
    }
    
    void Addedge(int x,int y,int l){
    	Adg(x , y , l); Adg(y , x , l);
    }
    
    void init(){
    	for(int i = 1 ; i <= N ; ++i)
    	for(int j = 1 ; j <= M ; ++j) if(mp[i][j] == '.'){
    		if(mp[i][j-1] == '#') Lm[i][j] = id(i , j);
    		else Lm[i][j] = Lm[i][j - 1];
    		if(mp[i-1][j] == '#') Um[i][j] = id(i , j);
    		else Um[i][j] = Um[i - 1][j]; 
    	} 
    	
    	for(int i = N ; i ; --i)
    	for(int j = M ; j ; --j) if(mp[i][j] == '.'){
    		if(mp[i][j+1] == '#') Rm[i][j] = id(i,j);
    		else Rm[i][j] = Rm[i][j + 1];
    		if(mp[i+1][j] == '#') Dm[i][j] = id(i,j);
    		else Dm[i][j] = Dm[i + 1][j]; 
    	}
    }
    
    void Build(){
    	for(int i = 1 ; i <= N ; ++i)
    	for(int j = 1 ; j <= M ; ++j) if(mp[i][j] == '.'){
    		if(mp[i][j + 1] == '.') Addedge(id(i,j),id(i,j+1),1);
    		if(mp[i + 1][j] == '.') Addedge(id(i,j),id(i+1,j),1);
    		if(Lm[i][j] != id(i , j)) Adg(id(i,j),Lm[i][j],md[i][j]);
    		if(Rm[i][j] != id(i , j)) Adg(id(i,j),Rm[i][j],md[i][j]);
    		if(Um[i][j] != id(i , j)) Adg(id(i,j),Um[i][j],md[i][j]);
    		if(Dm[i][j] != id(i , j)) Adg(id(i,j),Dm[i][j],md[i][j]);  
    	}
    }
    
    void Dijkstra(){
    	priority_queue<data>PQ;
    	for(int i = 1 ; i <= N*M ; ++i)
    		dis[i] = inf; 
    	dis[S] = 0; PQ.push((data){S,dis[S]});
    	while(!PQ.empty()){
    		int x = PQ.top().x,L = PQ.top().y;
    		PQ.pop();
    		if(L > dis[x]) continue;
    		for(int i = hed[x],v ; i ; i = nxt[i])
    			if(dis[v = to[i]] > dis[x] + len[i]){
    				//if(v == T) printf("%d
    ",x);
    				dis[v] = dis[x] + len[i];
    				PQ.push((data){v,dis[v]}); 
    			}
    	}
    }
    
    int main(){
    	freopen("cell.in","r",stdin);
    	freopen("cell.out","w",stdout);
    	scanf("%d%d",&N,&M);
    	for(int i = 1 ; i <= N ; ++i)
    		scanf("%s" , mp[i] + 1);
    	for(int i = 1 ; i <= N ; ++i)
    	for(int j = 1 ; j <= M ; ++j){
    		if(mp[i][j] == 'C') mp[i][j] = '.',S = id(i,j);
    		if(mp[i][j] == 'F') mp[i][j] = '.',T = id(i,j);
    	}
    	for(int i = 1 ; i <= N ; ++i)
    	for(int j = 1 ; j <= M ; ++j)
    		if(mp[i][j] == '#') Q.push((data){i,j});
    	Bfs(); init(); 
    	Build(); Dijkstra();
    	if(dis[T] != inf) printf("%d
    ",dis[T]);
    	else printf("no
    ");
    	
    	return 0;
    }
    
  • 相关阅读:
    突然想写一篇有关欧拉函数的博客
    洛谷P1199 三国游戏——题解
    洛谷P1310 表达式的值——题解
    洛谷P1309 瑞士轮——题解
    洛谷P1077 摆花——题解
    size_t是什么?
    c++ bitset——一个有趣的类型
    有关文件操作的总结
    一本通&&洛谷 ——靶型数独——题解
    一本通【例题4】Addition Chains——题解
  • 原文地址:https://www.cnblogs.com/shulker/p/9663138.html
Copyright © 2011-2022 走看看