zoukankan      html  css  js  c++  java
  • [NOIP2013]华容道

    输入输出样例

    输入样例#1:

    3 4 2
    0 1 1 1
    0 1 1 0
    0 1 0 0
    3 2 1 2 2 2
    1 2 2 2 3 2

    输出样例#1:

    2
    -1


    NOIP题好难啊QwQ

    不会

    暴力70分好打,正解emmmm

    我们发现一个问题就是只有空白块在要求块的旁边(上下左右)时才能带着ta满图跑

    所以我们用4个状态表示空白块在要求块的四个位置

    *0 : 在上面
    *1 : 在下面
    *2 : 在左边
    *3: 在右边

    然后就是以状态为点,每种状态向可以变成的状态连边

    最后跑最短路就行了

    然而我从网上粘了个题解><

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    const int M = 35 ;
    const int N = 4005 ;
    const int W = 100005 ;
    const int INF = 10000005 ;
    const int dx[4] = { -1 , 1 , 0 , 0 } ;
    const int dy[4] = { 0 , 0 , -1 , 1 } ;
    using namespace std ;
    inline int read() {
    	char c = getchar() ; int x = 0 , w = 1 ;
    	while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
    	while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
    	return x*w ;
    }
    struct Pos{ int x , y ; };
    struct Node { int Id , dis ;};
    inline bool operator < (Node a , Node b) { return a.dis > b.dis ; }
    int hea[N] , num ;
    struct E { int Nxt , to , Dis ;  }edge[W];
    inline void add_edge(int from , int to , int dis) {
    	edge[++num].Nxt = hea[from] ; edge[num].to = to ;
    	edge[num].Dis = dis ; hea[from] = num ;
    }
    int n , m , p[M][M] ;
    int dis[M][M] ;
    inline void Bfs(int Ex , int Ey , int Gx , int Gy , int Sit) {
    	queue< Pos > q ;
    	memset(dis , 0 , sizeof(dis)) ;
    	dis[Ex][Ey] = 1 ;
    	q.push((Pos) { Ex , Ey }) ;
    	while(!q.empty()) {
    		Pos temp = q.front() ; q.pop() ;
    		int x = temp.x , y = temp.y ;
    		for(int i = 0 ; i < 4 ; i ++) {
    			int Tx = x + dx[i] , Ty = y + dy[i] ;
    			if(Tx == Gx && Ty == Gy) continue ;
    			if(p[Tx][Ty] && !dis[Tx][Ty]) {
    			    dis[Tx][Ty] = dis[x][y] + 1 ;
    				q.push((Pos){ Tx , Ty }) ;
    			}
    		}
    	}
    //  先处理出一个格子周围的可移动的格子在不经过ta的情况下跑到其他位置的最短距离 
    	if(Sit < 0) return ;
    //	一个与(Gx,Gy)相邻的格子不经过(Gx,Gy)移动到其他与(Gx,Gy)相邻的格子 
    	for(int i = 0 , Tx , Ty ; i < 4 ; i ++) {  
    		Tx = Gx + dx[i] , Ty = Gy + dy[i] ;
    		if(Tx == Ex && Ty == Ey) continue ; if(!dis[Tx][Ty]) continue ;
    	    add_edge(Gx * 120 + Gy * 4 + Sit , Gx * 120 + Gy * 4 + i , dis[Tx][Ty] - 1) ;
    	}
    //  相邻的格子交换 
    	add_edge(Gx * 120 + Gy * 4 + Sit , Ex * 120 + Ey * 4 + (Sit^1) , 1) ;
    }
    int Dis[N] ;
    bool vis[N] ;
    inline void Dijkstra (int Gx , int Gy) { // 起点
    	priority_queue < Node > q ;
    	memset(Dis , 63 , sizeof(Dis)) ;
    	memset(vis , false , sizeof(vis)) ;
    	for(int i = 0 , Tx , Ty , u ; i < 4 ; i ++) { // 从空的格子移动到初始格子附近 
    		Tx = Gx + dx[i] , Ty = Gy + dy[i] ;
    		u = Gx * 120 + Gy * 4 + i ;
    		if(!dis[Tx][Ty]) continue ;
    		Dis[u] = dis[Tx][Ty] - 1 ;
    		q.push((Node){u , Dis[u]}) ;
    	}
    	while(!q.empty()) {
    		int u = q.top().Id ; q.pop() ;
    		if(vis[u]) continue ;
    		vis[u] = true ;
    		for(int i = hea[u] ; i ; i = edge[i].Nxt) {
    			int v = edge[i].to ;
    			if(!vis[v] && Dis[v] > Dis[u] + edge[i].Dis) {
    				Dis[v] = Dis[u] + edge[i].Dis ;
    				q.push((Node){v , Dis[v]}) ;
    			}
    		}
    	}
    }
    int main() {
    	n = read() ; m = read() ; int T = read() ;
    	for(int i = 1 ; i <= n ; i ++)
    	  for(int j = 1 ; j <= m ; j ++)
    	    p[i][j] = read() ;
    	for(int i = 1 ; i <= n ; i ++)
    	  for(int j = 1 ; j <= m ; j ++) {
    	  	if(!p[i][j]) continue ;
    	  	for(int k = 0 ; k < 4 ; k ++) {
    	  		int x = i + dx[k] , y = j + dy[k] ;
    	  		if(p[x][y]) Bfs(x , y , i , j , k) ;
    		}
    	  }
    	while(T -- ) {
    		int Ex = read() , Ey = read() , Sx = read() , Sy = read() , Tx = read() , Ty = read() ;		
    	    if(Sx == Tx && Sy == Ty) {printf("0
    ") ; continue ;}
    	    Bfs(Ex , Ey , Sx , Sy , -1) ; Dijkstra(Sx , Sy) ;
    	    int Ans = INF ;
    	    for(int i = 0 ; i < 4 ; i ++) 
    		// 空的格子移动到了目标格子周围 , 所以初始格子已经到了目标格子
    		//  枚举4种情况取最小值 
    		    Ans = min(Ans , Dis[Tx * 120 + Ty * 4 + i]) ;
    	    if(Ans < INF) printf("%d
    ",Ans) ;
    	    else printf("-1
    ") ;
    	}
    	return 0 ;
    }
    
  • 相关阅读:
    Bootstrap基础(七):按钮
    Bootstrap基础(六):表单
    Bootstrap基础(五):表格
    Bootstrap基础(四):代码
    Bootstrap基础(三):排版
    Bootstrap基础(二):网格系统
    Bootstrap基础(一):CSS 概览
    本人承接各种.Net网站制作,软件项目等业务。完美帮您定做
    iOS沙盒路径的查看和使用
    asp.net 源码坊4-6源码发布
  • 原文地址:https://www.cnblogs.com/beretty/p/9579975.html
Copyright © 2011-2022 走看看