题解 | #虫洞操纵者#java版本

虫洞操纵者

https://ac.nowcoder.com/acm/contest/87656/D

/*

最典型的bfs板子题,最困惑的点就是虫洞如何进行操作,我们直接对每个点进行爆搜即可, 四个方向需要进行分类讨论,因为他们最终的落点不相同,

着重注意的几个点:

1、数组我们要开n+2个,因为迷宫被墙包围,我们多开数组并把他们全部预处理为墙“1”

2、标记数组直接用来存储结果,所以我们不使用布尔数组来记录,简化代码

*/

import java.util.*;

public class Main{

static int n;
public static void main(String args[]){
    Scanner sc=new Scanner(System.in);
     n=sc.nextInt();
    int map[][]=new int[n+2][n+2];
    for(int i=1;i<= n;i++){
        for(int j=1; j<= n; j++){
            map[i][j]=sc.nextInt();
        }
    }
    for (int i = 0; i < n+2; i++) {
    //此处是在进行最外面的墙的预输入
        map[0][i]=1; map[n+1][i]=1;
        map[i][0]=1; map[i][n+1]=1;
    }
    int vis[][]=new int[n+2][n+2];
    //直接使用标记数组vis来记录数值
    for (int i = 0; i < n+2; i++) {
        for (int j = 0; j < n+2; j++) {
            vis[i][j]=-1;
        }
    }
    System.out.println(bfs(map,vis));
}
public static int bfs(int map[][] , int vis[][]){
    int dx[]=new int[]{0, 0,1,-1};
    int dy[]=new int[]{1,-1,0,0};
    Queue<int[]> q=new LinkedList<>();
    q.add(new int[]{1,1});
    vis[1][1]=0;
    //因为数组开大要存边界的墙,所以出发点是(1,1)
    while(!q.isEmpty()){
        int cur[]=new int[2];
        cur=q.poll();
        int x=cur[0];
        int y=cur[1];
        for (int i = 0; i < 4; i++) {
            int xx=x+dx[i],yy=y+dy[i];
            if (xx < 0 || xx >= n + 2 || yy < 0 || yy >= n + 2) continue;
            if(vis[xx][yy]!=-1) continue;
            //接下来的四个判断语句用来进行虫洞的穿越
            if(map[xx][yy]==1){//碰到墙了,开始进行虫洞的穿越
                if(i==0){
                    for (int j = y; j >= 0; j--) {
                        if(map[xx][j]==1){
                            xx=x; yy=j+1;
                            break;
                        }
                    }
                }
                else if(i==1){
                    for (int j = y; j < n+2; j++) {
                        if(map[xx][j]==1){
                            xx=x; yy=j-1;
                            break;
                        }
                    }
                }
                else if(i==2){
                    for (int j = x; j >=0 ; j--) {
                        if(map[j][yy]==1){
                            yy=y;xx=j+1;
                            break;
                        }
                    }
                }
                else {
                    for (int j = x; j < n+2 ; j++) {
                        if(map[j][yy]==1){
                            yy=y;xx=j-1;
                            break;
                        }
                    }
                }
                //如果vis的值不是-1,证明这个点已经被访问过,直接打断即可
                if(vis[xx][yy]!=-1) continue;
                //此处我们要继承上一个点的值,所以有很多人想到了dp
                vis[xx][yy]=vis[x][y]+1;
                q.add(new int[]{xx,yy});

            } else{//移动的时候没有碰到墙,正常移动进行+1
                vis[xx][yy]=vis[x][y]+1;
                q.add(new int[]{xx,yy});
            }
        }

    }
    return vis[n][n];
}

}

全部评论

相关推荐

03-30 19:30
石家庄学院 Java
野蛮的柯基在游泳:都能入股了,还得是Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务