day03 第十三届蓝桥杯国赛 JavaB

day03

🎉前言:每日更新!不断更!,周内一天一题.周末算法精析

✨更新地址:Royeblog

🎆🎆第十三届国赛javaB 试题 E: 迷宫

🎉题目链接:题号2222

简单描述题目:

【问题描述】
这天,小明在玩迷宫游戏。 迷宫为一个n * n的网格图,小明可以在格子中移动,左上角为(1; 1),右 下角(n; n) 为终点。迷宫中除了可以向上下左右四个方向移动一格以外,还有 m个双向传送门可以使用,传送门可以连接两个任意格子。 假如小明处在格子(x1; y1),同时有一个传送门连接了格子(x1; y1) 和(x2; y2),那么小明既可以花费1 的步数向上下左右四个方向之一走一格(不能 越过边界),也可以花费1 的步数通过传送门走到格子(x2; y2) 去。而对于同一个迷宫,小明每次进入的初始格子是在这n * n 个格子中均匀随机的(当然运气好可以直接随机到终点),他想知道从初始格子走到终点的最短 步数的期望值是多少。
【输入格式】
输入共1 + m行,第一行为两个正整数n;m。 后面m 行,每行四个正整数xi1; yi1; xi2; yi2 表示第i 个传送门连接的两个格子坐标。
【输出格式】
输出共一行,一个浮点数表示答案(请保留两位小数)。
【样例输入】

2 1
1 1 2 2

【样例输出】

0.75

【样例解释】
由于传送门的存在,从(1; 1) 出发到终点(2; 2) 只需要一步;而从(1; 2) 和 (2; 1) 出发也只需要向下/右走一步;从(2; 2) 出发需要0 步。所以步数期望为 (1+1+1+0)/ (2*2) = 0:75。
【评测用例规模与约定】
对于20% 的数据,保证n;m <= 20; 对于100% 的数据,保证n;m <= 2000; xi1; yi1; xi2; yi2 <= n。

import java.util.*;

public class D迷宫 {
    static class node {
        int x;
        int y;
        int step;

        public node(int x, int y, int step) {
            this.x = x;
            this.y = y;
            this.step = step;
        }

    }

    public static void main(String[] args) {
        int[] dx = {0, 0, 1, -1};
        int[] dy = {1, -1, 0, 0};

        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        //从n,n到该点的最低步数
        int[][] arrmap = new int[n+1][n+1];
        //存储传送门 从x1,y1到x2,y2
        //将x1,y1以x1*n+y1的形式保存为integer  用list表示多个门传送到同一个门
        Map<Integer,List<int[]>> map=new HashMap<>();

        for (int i = 0; i < m; i++) {
            int x1 = sc.nextInt();
            int y1 = sc.nextInt();
            int x2 = sc.nextInt();
            int y2 = sc.nextInt();
            if (!map.containsKey(x1*n+y1)){
                map.put(x1*n+y1,new ArrayList<>());
            }
            map.get(x1*n+y1).add(new int[]{x2, y2});
            //双向传送门
            if (!map.containsKey(x2*n+y2)){
                map.put(x2*n+y2,new ArrayList<>());
            }
            map.get(x2*n+y2).add(new int[]{x1, y1});
        }
        //经典BFS模板
        Queue<node> list = new LinkedList<>();
        list.add(new node(n, n, 0));
        while (!list.isEmpty()) {
            node pop = list.poll();
            int movex,movey;
            //如果有传送门就传送
            if (map.containsKey(pop.x*n+ pop.y)){
                for (int[] ints : map.get(pop.x * n + pop.y)) {
                    movex=ints[0];
                    movey=ints[1];
                    if (movey == 0) {
                        movex --;
                        movey = n;
                    }
                    if (arrmap[movex][movey]==0){
                        list.add(new node(movex,movey, pop.step+1));
                        arrmap[movex][movey]= pop.step+1;
                    }
                }

            }
            //没有就遍历上下左右
            for (int i = 0; i < 4; i++) {
                movex= pop.x+dx[i];
                movey= pop.y+dy[i];
                if (movex>0&&movey>0&&movex<=n&&movey<=n&&arrmap[movex][movey]==0){
                    list.add(new node(movex,movey,pop.step+1));
                    arrmap[movex][movey]= pop.step+1;
                }
            }
        }
        int sum=0;
        for (int i = 1; i < arrmap.length; i++) {
            for (int j = 1; j < arrmap.length; j++) {
                sum+=arrmap[i][j];
            }
        }
        //n,n会被覆盖不为0减去就好
        sum-=arrmap[n][n];
        System.out.printf("%.2f",sum*1.0/(n*n));
    }
}

经典BFS题,注释很清楚!主要是对于传送门的理解,是双向传送门,可以有多个门传送到同一个地方,改了好几次才ac,题本来不难,主要是对传送门处理,例如integer=x1*n+y1和用map存储多个门,加油吧少年们! 👍

❗❗总结:好好学习每一天
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值