2018今日头条校招大数据方向第三批编程题2

链接:https://www.nowcoder.com/questionTerminal/1f8d61e3090644d8996fdec01694d3cf
来源:牛客网
 

有一个推箱子的游戏, 一开始的情况如下图:

2018今日头条校招大数据方向第三批编程题2_第1张图片

上图中, '.' 表示可到达的位置, '#' 表示不可到达的位置,其中 S 表示你起始的位置, 0表示初始箱子的位置, E表示预期箱子的位置,你可以走到箱子的上下左右任意一侧, 将箱子向另一侧推动。如下图将箱子向右推动一格;

..S0.. -> ...S0.

注意不能将箱子推动到'#'上, 也不能将箱子推出边界;

现在, 给你游戏的初始样子, 你需要输出最少几步能够完成游戏, 如果不能完成, 则输出-1。

 

输入描述:

第一行为2个数字,n, m, 表示游戏盘面大小有n 行m 列(5< n, m < 50);
后面为n行字符串,每行字符串有m字符, 表示游戏盘面;

输出描述:

一个数字,表示最少几步能完成游戏,如果不能,输出-1;

示例1

输入

3 6
.S#..E
.#.0..
......

输出

11

难点

1、最短步数,可以使用BFS求得

常规BFS,可用Boolean数组记录是否已到达,避免重复添加路径。仅使用Boolean数组即可判断当前路径已走过的前提是,BFS每一层默认步数+1,假设当前位置为P,则从初始位置S到P的最短路径即为最开始搜索到P的路径,故若P已被访问过,则最短路径已被找到,以后再搜索到P,最短路径也不可能短于最初的最短路径了。

但此题有特殊之处,箱子每推动一次,人走的路程由两部分组成:Step1、由原来的位置走到箱子的某一侧的最短步数,Step2、向前推动一步。其中Step1并非固定为1,有可能是0或2,若途中有障碍,甚至会更长,因此仅用Boolean数组已不能确定访问过的P即是最短路径了,需要记录访问到P的最短步数,并比较,若当前的最短步数小于记录的最短步数,需要更新,否则可抛弃。

代码中的visit数组含义为:以往箱子推到位置P时花费的最少步数。

Step1本身求取可使用常规BFS,但箱子的路径添加需要记录每个位置的最短步数

 

2、此外,注意人不能从箱子所在的位置经过,因此要时时更新箱子的位置

 

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

import static java.lang.System.out;

public class Main_2 {
    public static boolean check(char[][] board,int r,int c,int target_i,int target_j){
        if(target_i<0||target_j<0||target_i>=r||target_j>=c) return false;
        char ch=board[target_i][target_j];
        if(ch=='#'||ch=='0') return false;//
        return true;
    }
    public static int SD(char[][] board,int r0,int c0,int rt,int ct){
        int n=board.length,m=board[0].length;
        if(!check(board,n,m,rt,ct)) return -1;
        if(r0==rt&&c0==ct) return 0;
        boolean[][] visit=new boolean[n][m];
        Queue q=new LinkedList();
        int[] cur={r0,c0,0};
        visit[r0][c0]=true;
        q.offer(cur);
        while(!q.isEmpty()){
            cur=q.poll();
            if(check(board,n,m,cur[0]+1,cur[1])&&visit[cur[0]+1][cur[1]]==false){
                if(cur[0]+1==rt&&cur[1]==ct) return cur[2]+1;
                visit[cur[0]+1][cur[1]]=true;
                int[] tmp={cur[0]+1,cur[1],cur[2]+1};
                q.offer(tmp);
            }
            if(check(board,n,m,cur[0]-1,cur[1])&&visit[cur[0]-1][cur[1]]==false){
                if(cur[0]-1==rt&&cur[1]==ct) return cur[2]+1;
                visit[cur[0]-1][cur[1]]=true;
                int[] tmp={cur[0]-1,cur[1],cur[2]+1};
                q.offer(tmp);
            }
            if(check(board,n,m,cur[0],cur[1]+1)&&visit[cur[0]][cur[1]+1]==false){
                if(cur[0]==rt&&cur[1]+1==ct) return cur[2]+1;
                visit[cur[0]][cur[1]+1]=true;
                int[] tmp={cur[0],cur[1]+1,cur[2]+1};
                q.offer(tmp);
            }
            if(check(board,n,m,cur[0],cur[1]-1)&&visit[cur[0]][cur[1]-1]==false){
                if(cur[0]==rt&&cur[1]-1==ct) return cur[2]+1;
                visit[cur[0]][cur[1]-1]=true;
                int[] tmp={cur[0],cur[1]-1,cur[2]+1};
                q.offer(tmp);
            }
        }
        return -1;
    }
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n=scan.nextInt(),m=scan.nextInt();
        scan.nextLine();
        char[][] board=new char[n][m];
        int [][] visit=new int[n][m];
        for(int i=0;i q=new LinkedList();
        int[] s={b_i,b_j,h_i,h_j,0};
        visit[b_i][b_j]=0;
        board[b_i][b_j]='.';
        board[h_i][h_j]='.';
        q.offer(s);

//        out.println("终点:("+e_i+","+e_j+")");
        while(!q.isEmpty()){
            int[] cur=q.poll();
            board[cur[0]][cur[1]]='0';
            if(cur[4]>=max){
                board[cur[0]][cur[1]]='.';
                continue;
            }
//            out.println("箱子所在位置: ("+cur[0]+","+cur[1]+")");
            if(check(board,n,m,cur[0]+1,cur[1])){//&&visit[cur[0]+1][cur[1]]==false
                int add=SD(board,cur[2],cur[3],cur[0]-1,cur[1])+1;
                if(add>0&&cur[4]+addcur[4] + add) {
                            visit[cur[0] + 1][cur[1]] = cur[4] + add;
                            q.offer(tmp);
                        }
                    }
                }
            }
            if(check(board,n,m,cur[0]-1,cur[1])){//&&visit[cur[0]-1][cur[1]]==false
                int add=SD(board,cur[2],cur[3],cur[0]+1,cur[1])+1;
                if(add>0&&cur[4]+addcur[4] + add) {
                            visit[cur[0] - 1][cur[1]] = cur[4] + add;
                            q.offer(tmp);
                        }

                    }
                }
            }
            if(check(board,n,m,cur[0],cur[1]+1)){//&&visit[cur[0]][cur[1]+1]==false
                int add=SD(board,cur[2],cur[3],cur[0],cur[1]-1)+1;
                if(add>0&&cur[4]+addcur[4] + add) {
                            visit[cur[0]][cur[1]+1] = cur[4] + add;
                            q.offer(tmp);
                        }
                    }
                }
            }
            if(check(board,n,m,cur[0],cur[1]-1)){//&&visit[cur[0]][cur[1]-1]==false
                int add=SD(board,cur[2],cur[3],cur[0],cur[1]+1)+1;
                if(add>0&&cur[4]+addcur[4] + add) {
                            visit[cur[0]][cur[1]-1] = cur[4] + add;
                            q.offer(tmp);
                        }
                    }
                }
            }
            board[cur[0]][cur[1]]='.';
        }
        out.println(max==Integer.MAX_VALUE?-1:max);
    }
}

 

你可能感兴趣的:(求职)