• UVALive 6888 Ricochet Robots bfs


    Ricochet Robots

    题目连接:

    http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=129726

    Description

    A team of up-to four robots is going to deliver parts in
    a factory floor. The floor is organized as a rectangular
    grid where each robot ocupies a single square cell.
    Each robot is represented by an integer from 1 to 4
    and can move in the four orthogonal directions (left,
    right, up, down). However, once set in motion, a robot
    will stop only when it detects a neighbouring obstacle
    (i.e. walls, the edges of the factory or other stationary
    robots). Robots do not move simultaneously, i.e. only
    a single robot moves at each time step.
    The goal is to compute an efficient move sequence
    such that robot 1 reaches a designed target spot; this
    may require moving other robots out of the way or to
    use them as obstacles for “ricocheting” moves.
    Consider the example given above, on the right,
    where the gray cells represent walls, X is the target
    location and ⃝1 , ⃝2 mark the initial positions of two robots. One optimal solution consists of the six
    moves described below.
    ⃝2
    ⃝1
    X
    ⃝1 moved up.
    ⃝1
    ⃝2 X
    ⃝2 moved right, down and left.
    ⃝2 ⃝1
    ⃝1 moved down and left.
    Note that the move sequence must leave robot 1 at the target location and not simply pass through
    it (the target does not cause robots to stop — only walls, edges and other robots).
    Given the description of the factory floor plan, the initial robot and target positions, compute the
    minimal total number of moves such that robot 1 reaches the target position.

    Input

    The input file contains several test cases, each of them as described below.
    The first line contains the number of robots n, the width w and height h of the factory floor in cells,
    and an upper-bound limit ℓ on the number of moves for searching solutions.
    The remaining h lines of text represent rows of the factory floor with exactly w characteres each
    representing a cell position:
    ‘W’ a cell occupied by a wall;
    ‘X’ the (single) target cell;
    ‘1’,‘2’,‘3’,‘4’ initial position of a robot;
    ‘.’ an empty cell.
    Constraints:
    1 ≤ n ≤ 4
    max(w, h) ≤ 10
    w, h ≥ 1
    1 ≤ ℓ ≤ 10

    Output

    For each test case, the output should be the minimal number of moves for robot 1 to reach the target
    location or ‘NO SOLUTION’ if no solution with less than or equal the given upper-bound number of moves
    exists.

    Sample Input

    2 5 4 10
    .2...
    ...W.
    WWW..
    .X.1.
    1 5 4 10
    .....
    ...W.
    WWW..
    .X.1.

    Sample Output

    6
    NO SOLUTION

    Hint

    题意

    给你一个棋盘,棋盘上面有最多四个棋子,你的目标是把一号棋子走到X位置,你可以动棋子,棋子的话,只能往四个方向走,走必须走到底,除非碰到边界或者墙,或者其他棋子。
    让你在l步以内输出最小节,问你能不能。

    题解:

    一眼搜索题,但是究竟是dfs还是bfs呢?

    他给你了个上界,所以一般就直接思考bfs了,而不是dfs

    所以直接bfs莽一波就好了,没啥好说的呢,剩下就是码码码。

    代码

    #include <bits/stdc++.h>
    #define rep(a,b,c) for(int (a)=(b);(a)<=(c);++(a))
    #define drep(a,b,c) for(int (a)=(b);(a)>=(c);--(a))
    #define pb push_back
    #define mp make_pair
    #define sf scanf
    #define pf printf
    #define two(x) (1<<(x))
    #define clr(x,y) memset((x),(y),sizeof((x)))
    #define dbg(x) cout << #x << "=" << x << endl;
    #define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0)
    inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
    using namespace std;
    const int maxn = 10 + 5;
    const int mod = 100000;
    int extra[8]={123,115,65147,233,6421,7361,73561,442};
    int num,N,M,Limit,Up[maxn][maxn],Down[maxn][maxn],Lft[maxn][maxn],Rht[maxn][maxn],targetX,targetY;
    char G[maxn][maxn];
    
    bool inmap(int x , int y){ return 1 <= x && x <= N && 1 <= y && y <= M; }
    
    int Got_Up(int x , int y){
    	if(!inmap(x,y)||G[x][y]=='W') return 0;
    	if(~Up[x][y]) return Up[x][y];
    	return Up[x][y]=Got_Up(x-1,y)+1;
    }
    
    int Got_Down(int x , int y){
    	if(!inmap(x,y)||G[x][y]=='W') return 0;
    	if(~Down[x][y]) return Down[x][y];
    	return Down[x][y]=Got_Down(x+1,y)+1;
    }
    int GOt_Lft(int x , int y){
    	if(!inmap(x,y)||G[x][y]=='W') return 0;
    	if(~Lft[x][y]) return Lft[x][y];
    	return Lft[x][y]=GOt_Lft(x,y-1)+1;
    }
    int Got_Rht(int x , int y){
    	if(!inmap(x,y)||G[x][y]=='W') return 0;
    	if(~Rht[x][y]) return Rht[x][y];
    	return Rht[x][y]=Got_Rht(x,y+1)+1;
    }
    
    struct Data{
    	pair < int , int > p[4] ;
    	int step ;
    
    	int cal_hash(){
    		int tot = 0  ;
    		long long A = 0;
    		rep(i,0,num-1){
    			A += p[i].first * extra[tot ++ ];
    			A += p[i].second * extra[tot ++ ];
    		}
    		if( A >= mod ) A %= mod;
    		return (int)A;
    	}
    
    	Data( const pair < int , int > & a , const pair < int , int > & b , const pair < int , int > & c , const pair < int , int > & d , int sp ){ p[0]= a,p[1]=b,p[2]=c,p[3]=d,step=sp; }
    };
    
    
    vector < Data > Judge[mod];
    pair < int , int > base[4];
    queue < Data > Q;
    
    void Try_Push( Data & np ){
    	if(np.step > Limit) return ;
    	int h = np.cal_hash();
    	for(auto it : Judge[h] ){
    		int ok = 1;
    		rep(j,0,num - 1)
    			if(it.p[j]!=np.p[j]){
    				ok = 0 ;
    				break;
    			}
    		if(ok) return ;
    	}
    	Q.push( np );
    	Judge[h].pb(np);
    }
    
    void Init(){
    	for(int i = 0 ; i < mod ; ++ i) Judge[i].clear();
    }
    
    int bfs(){
    	while(!Q.empty()) Q.pop();
    	Q.push( Data( base[0] , base[1] , base[2] , base[3] , 0 ));
    	while(!Q.empty()){
    		Data fq = Q.front() ; Q.pop();
    		if( fq.p[0].first == targetX && fq.p[0].second == targetY ) return fq.step;
    		if( fq.step == Limit ) continue;
    		for(int idx = 0 ; idx <= num - 1 ; ++ idx ){
    			// 准备移动第 idx 个
    			pair < int , int > pos = fq.p[idx]; // 获得初始位置
    
    			//cout << "Come here " << endl;
    
    			int x  = pos.first , y = pos.second;
    			// 向上
    			{
    				pair < int , int > nxtpos = mp( pos.first - Up[x][y] , pos.second );
    				rep(j,0,num - 1){
    					if( fq.p[j].second == y && fq.p[j].first < pos.first && fq.p[j].first >= nxtpos.first  ){
    						nxtpos.first = fq.p[j].first + 1;
    					}
    				}
    
    				//cout << x << " " << y << " Up " << Up[x][y] << endl;
    				//assert( inmap( nxtpos.first , nxtpos.second ));
    				if(nxtpos.first != x){
    					Data newst = fq;
    					newst.p[idx] = nxtpos;
    					newst.step ++ ;
    					Try_Push( newst );
    				}
    
    			}
    
    			// 向下
    			{
    
    				pair < int , int > nxtpos = mp( pos.first + Down[x][y] , pos.second );
    				rep(j,0,num - 1){
    					if( fq.p[j].second == y && fq.p[j].first <= nxtpos.first && fq.p[j].first > pos.first  ){
    						nxtpos.first = fq.p[j].first - 1;
    					}
    				}
    
    				//				cout << x << " " << y << " Down " << Down[x][y] << endl;
    				//assert( inmap( nxtpos.first , nxtpos.second ));
    				if(nxtpos.first != x){
    					Data newst = fq;
    					newst.p[idx] = nxtpos;
    					newst.step ++ ;
    					Try_Push( newst );
    				}
    
    			}
    
    
    			// 向左
    			{
    				pair < int , int > nxtpos = mp( pos.first , pos.second - Lft[x][y] );
    				rep(j,0,num - 1){
    					if( fq.p[j].first == x && fq.p[j].second < pos.second && fq.p[j].second >= nxtpos.second  ){
    						nxtpos.second = fq.p[j].second + 1;
    					}
    				}
    
    				//				cout << x << " " << y << " Lft " << Lft[x][y] << endl;
    				//assert( inmap( nxtpos.first , nxtpos.second ));
    				if(nxtpos.second != y){
    					Data newst = fq;
    					newst.p[idx] = nxtpos;
    					newst.step ++ ;
    					Try_Push( newst );
    				}
    
    			}
    
    			// 向右
    			{
    
    				pair < int , int > nxtpos = mp( pos.first , pos.second + Rht[x][y] );
    				rep(j,0,num - 1){
    					if( fq.p[j].first == x && fq.p[j].second <= nxtpos.second && fq.p[j].second > pos.second  ){
    						nxtpos.second = fq.p[j].second - 1;
    					}
    				}
    
    				//				cout << x << " " << y << " Rht " << Rht[x][y] << endl;
    				//assert( inmap( nxtpos.first , nxtpos.second ));
    				if(nxtpos.second != y){
    					Data newst = fq;
    					newst.p[idx] = nxtpos;
    					newst.step ++ ;
    					Try_Push( newst );
    				}
    			}
    
    		}
    	}
    	return -1;
    }
    
    int main(int argc,char *argv[]){
    	while(~scanf("%d%d%d%d",&num,&M,&N,&Limit)){
    		rep(i,1,N) sf("%s",G[i] + 1);
    		clr(Lft,-1);clr(Up,-1);clr(Down,-1);clr(Rht,-1);
    		rep(i,1,N) rep(j,1,M){
    			GOt_Lft(i,j);Got_Up(i,j);Got_Down(i,j);Got_Rht(i,j);
    		}
    		rep(i,1,N)rep(j,1,M){
    			Up[i][j]--;
    			Down[i][j]--;
    			Lft[i][j]--;
    			Rht[i][j]--;
    		}
    		rep(i,1,N) rep(j,1,M){
    			if(G[i][j]<='4'&&G[i][j]>='1'){
    				int idx = G[i][j] - '1';
    				base[idx] = mp( i , j );
    			}else if(G[i][j]=='X'){
    				targetX = i , targetY = j;
    			}
    		}
    		int ans = bfs();
    		if( ans == -1 ) pf("NO SOLUTION
    ");
    		else pf("%d
    ",ans);
    		Init();
    	}
    	return 0;
    }
  • 相关阅读:
    JAVA-AbstractQueuedSynchronizer-AQS
    线程封闭
    安全发布对象
    JAVA并发基础
    C#JsonConvert.DeserializeObject反序列化json字符
    Java并发容器
    JAVA简易数据连接池Condition
    Java线程读写锁
    JDK提供的原子类和AbstractQueuedSynchronizer(AQS)
    协方差矩阵分解的物理意义
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5677522.html
Copyright © 2020-2023  润新知