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;
    }
    
  • 相关阅读:
    Oracle 推出 ODAC for Entity Framework 和 LINQ to Entities Beta版
    Entity Framework Feature CTP 5系列文章
    MonoDroid相关资源
    MSDN杂志上的Windows Phone相关文章
    微软学Android Market推出 Web Windows Phone Marketplace
    使用 Visual Studio Agent 2010 进行负载压力测试的安装指南
    MonoMac 1.0正式发布
    Shawn Wildermuth的《Architecting WP7 》系列文章
    使用.NET Mobile API即51Degrees.mobi检测UserAgent
    MongoDB 客户端 MongoVue
  • 原文地址:https://www.cnblogs.com/shulker/p/9663138.html
Copyright © 2011-2022 走看看