[华为OD]BFS C卷 200 智能驾驶

news2024/12/27 13:34:59

题目:

有一辆汽车需要从m*n的地图的左上角(起点)开往地图的右下角(终点),去往每一个地区都需 

要消耗一定的油量,加油站可进行加油

请你计算汽车确保从起点到达终点时所需的最少初始油量说明:

(1)智能汽车可以上下左右四个方向移动1

⑵地图上的数字取值是0或-1或者正整数:

-1:表示加油站,可以加满油,汽车的油箱容量最大为100;

0:表示这个地区是障碍物,汽车不能通过

正整数:表示汽车走过这个地区的耗油量

⑶如果汽车无论如何都无法到达终点,则返回-1

输入描述

第一行为两个数字,M, V,表示地图的大小为M,N(0< M,N < 200)

后面一个M*N的矩阵,其中的值是0或-1或正整数,加油站的总数不超过200个

输出描述

如果汽车无论如何都无法到达终点,则返回-1

如果汽车可以到达终点,则返回最少的初始油量

示例1 

输入

2,2 

10,20 

30,40

输出

70

示例2 

输入

4,4 

10,30,30,20 

30,30,-1,10 

0,20,20,40

10,-1,30,40 

输出

70

示例3

输入

4,5

10,0,30,-1,10 

30,0,20,0,20 

10,0,10,0,30 

10,-1,30,0,10 

输出

60

示例4

输入

4,4

10,30,30,20 

30,30,20,10 

10,20,10,40 

10,20,30,40 

输出

-1

题解:这个题目要计算最少初始油料,那么如果经过加油站的话,明显就要直接加满油。

比较明显的BFS题目。但是需要判断到加油站的情况。由于油箱容量100,那么我们出发时候就将当前油量设置为100。

依旧还是需要定义一个内部类,参数有x,y坐标。这个里面就加了,初始油量originalOil,当前坐标走完需要油量needOil,也就是矩阵中当前的值。以及汽车在这个坐标的剩余油量restOil,还有一个bool值,是否有在加油站加过油。

1)如果到加油站时候,车辆没有加过油,那么从出发到这个加油站的初始油量(刚出发时候初始油量)就可以变为100减去当前剩余油量了。

2)当BFS向下一坐标搜索的时候,如果restOil剩余油量不足以满足去下一个坐标需要的油量needOil,那么就继续往下搜索

3)在到终点的时候,如果没有加过油,那么如果剩余油量>0,那么这个路径走下来的初始油量应该可以变成100减去当前剩余油量

4)当走到任意坐标时候,油量足够,而且汽车加过油,那么初始油量应该不变,因为加过油,剩余油量在加油站那个坐标直接变为100了

5)走过一个坐标,那么这个坐标访问标记visit[x][y]=1;

这个里面可以看到有一个难点就是可能有两条路线能经过同一个加油站,两条路径油量不同,如何确保最终是最少油量经过这个加油站。这边采用的是一个map<String,Integer> oilStations来解决表示的是这个加油站坐标和来这个加油站最少得油量。因为在初始化扫描的时候当矩matrixs[i][j]==-1,就是加油站,那么此时就初始化这个加油站油量为Integer.MaxValue.

6)那么在经过加油站的坐标时候,加油站坐标的visit[x][y],还是为0,不能变为1,防止其他路径更少油量,由于visit[x][y]==1,而不能到加油站,结果就不对。此时,先根据oilStations,拿到抵达这个加油站当前的最少油量prsentLeastOil,如果这个路径到这个加油站的最少油量小于

prsentLeastOil,那么说明现在这个路径就更优,那么就把这个路径继续扫描下去,也就是将这个路径的点加入到队列中去。如果大于等于,这条路径就不用继续扫描了,明显不是最优解,不能为等于是因为防止两个加油站相邻,那么等于的话,明显路径会在这两个加油站一直循环扫。

7)用一个列表表示每个到终点的路径最少油量,最后排序取第一个值就是最少初始油量了

这个题感觉难度就在处理加油站的逻辑上面。

代码:

import java.util.*;

public class CarPath {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] matrix = sc.nextLine().split(",");
        int m = Integer.valueOf(matrix[0]);
        int n = Integer.valueOf(matrix[1]);
        int matrixs[][] = new int[m][n];
        int visit[][] = new int[m][n];
        Map<String, Integer> oilStations = new HashMap<>();
        for (int i = 0; i < m; i++) {
            String[] data = sc.nextLine().split(",");
            for (int j = 0; j < n; j++) {
                matrixs[i][j] = Integer.valueOf(data[j]);
                visit[i][j] = 0;
                if (matrixs[i][j] == -1) {
                    oilStations.put(String.valueOf(i) + String.valueOf(j), Integer.MAX_VALUE);
                }
            }
        }

        int startX = 0;
        int startY = 0;
        int endX = m - 1;
        int endY = n - 1;
        Path startPath = new Path(startX, startY, matrixs[0][0], 100 - matrixs[0][0]);
        startPath.originalOil = 100;
        visit[0][0] = 1;
        Queue<Path> queue = new LinkedList<>();
        queue.offer(startPath);

        List<Integer> needOil = new ArrayList<>();
        boolean hasRoote = false;

        int dirctions[][] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};

        // BFS
        while (!queue.isEmpty()) {
            Path frontPath = ((LinkedList<Path>) queue).getFirst();
            if (frontPath.x == endX && frontPath.y == endY) {
                hasRoote = true;
                ((LinkedList<Path>) queue).pollFirst();
                continue;
            }

            for (int i = 0; i < 4; i++) {
                int newX = frontPath.x + dirctions[i][0];
                int newY = frontPath.y + dirctions[i][1];

                if (newX >= 0 && newX < m && newY >= 0 && newY < n) {
                    System.out.println("newX " + newX + " newY " + newY);
                    if (newX == 3 && newY == 3) {
                        System.out.println("error0");
                    }
                    if (newX == endX && newY == endY) { // 下一个是终点
                        Path endPath = new Path(newX, endY, matrixs[newX][newX], frontPath.getRestOil() - matrixs[newX][newX]);
                        if (endPath.restOil < 0) { // 油不足以走到终点
                            continue;
                        } else {
                            if (frontPath.hasAddOil) { //加过油
                                endPath.originalOil = frontPath.originalOil;
                            } else {//全程没有加过油 并且有多的油
                                endPath.originalOil = frontPath.originalOil - endPath.restOil;
                            }
                            needOil.add(endPath.originalOil);
                            hasRoote = true;
                            queue.offer(endPath);
                            continue;
                        }
                    }

                    if (matrixs[newX][newY] != 0 && matrixs[newX][newY] != -1 && visit[newX][newY] == 0) { //下一个是一般道路
                        Path nextPath = new Path(newX, newY, matrixs[newX][newY],
                                frontPath.getRestOil() - matrixs[newX][newY]);
                        if (nextPath.restOil < 0) { // 油不足以走到终点
                            continue;
                        } else {
                            nextPath.hasAddOil = frontPath.hasAddOil;
                            if (frontPath.hasAddOil) {//加过油
                                nextPath.originalOil = frontPath.originalOil;
                            } else { //没加过油 需要的油就要加上当前道路需要的油
                                nextPath.originalOil = frontPath.originalOil;
                            }
                        }
                        if (nextPath.x == 3 && nextPath.y == 3) {
                            System.out.println("error");
                        }
                        queue.offer(nextPath);
                        visit[newX][newY] = 1;
                        continue;
                    }

                    if (matrixs[newX][newY] == 0) {
                        visit[newX][newY] = 1;
                        continue;
                    }
                    if (matrixs[newX][newY] == -1 && visit[newX][newY] == 0) { // 到加油站了,这个题明显到加油站都得加满油
                        Integer prsentLeastOil = oilStations.get(String.valueOf(newX) + String.valueOf(newY));
                        if (frontPath.restOil >= prsentLeastOil) {
                            continue;
                        }
                        oilStations.put(String.valueOf(newX) + String.valueOf(newY), frontPath.restOil);
                        Path nextPath = new Path(newX, newY, matrixs[newX][newY],
                                100);// 加油站直接加满油
                        nextPath.hasAddOil = true;
                        if (!frontPath.hasAddOil) {// 前面没有加过油
                            nextPath.originalOil = frontPath.originalOil - frontPath.restOil;// 需要的油应该是前车需要的油料减去前车剩余油料,因为初始化是100
                        } else { // 前面已经加过油
                            nextPath.originalOil = frontPath.originalOil;
                        }
                        visit[newX][newY] = 0;  //加油站不设置访问标记 通过判断到加油站剩余油料是最少得来判断是否将当前数据加入队列,继续扫描
                        if (nextPath.x == 3 && nextPath.y == 3) {
                            System.out.println("error1");
                        }
                        queue.offer(nextPath);
                        continue;
                    }
                }
            }

            ((LinkedList<Path>) queue).pollFirst(); //首元素推出队列
        }

        if (hasRoote) {
            Collections.sort(needOil);
            System.out.println(needOil.get(0));
        } else {
            System.out.println(-1);
        }


    }

    private static class Path {
        int x;
        int y;
        int needOil;
        int restOil;
        int originalOil;
        boolean hasAddOil;//是否加过油

        public Path(int x, int y, int needOil) {
            this.x = x;
            this.y = y;
            this.needOil = needOil;
        }

        public Path(int x, int y, int needOil, int restOil) {
            this.x = x;
            this.y = y;
            this.needOil = needOil;
            this.restOil = restOil;
        }


        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }

        public int getNeedOil() {
            return needOil;
        }

        public void setNeedOil(int needOil) {
            this.needOil = needOil;
        }

        public int getRestOil() {
            return restOil;
        }

        public void setRestOil(int restOil) {
            this.restOil = restOil;
        }

        public Path(int originalOil) {
            this.originalOil = originalOil;
        }

        public Path(boolean hasAddOil) {
            this.hasAddOil = hasAddOil;
        }
    }
}

验证:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1670058.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python中的`__init__.py`文件:它的作用和重要性

引言 在Python的世界里&#xff0c;__init__.py文件是一个特殊的存在。对于初学者来说&#xff0c;它可能看起来有些神秘&#xff0c;但对于理解Python的包和模块系统来说&#xff0c;它起着至关重要的作用。本文将详细解释__init__.py文件的功能、它在Python项目中的作用&…

Threejs实现PMD模型眨眼说话等功能

上个章节通过加载PMD模型和VMD的动作播放MMD的动画&#xff0c;这节通过js控制让模型实现眨眼&#xff0c;说话。我们还是拿上个模型来操作&#xff0c;首先是创建好Threejs的场景&#xff0c;包括灯光&#xff0c;相机&#xff0c;渲染器等。 initScene(){this.scene new THR…

【Linux】Centos7安装部署unimrcp,搭建MRCP服务器

yum install libtool yum install libtool-ltdl-devel yum install libsofia-sip-ua find / -name libsofia-sip-ua.so.0 2>/dev/null # 设置环境变量&#xff1a;如果库文件存在但不在默认搜索路径中&#xff0c;你可以通过设置 LD_LIBRARY_PATH 环境变量来告诉系统在哪…

语音转文字服务的调用接口

语音转文字&#xff08;Speech-to-Text&#xff0c;STT&#xff09;技术允许将口语化的语音转换成书面文字。以下是一些提供语音转文字服务的调用接口及其特点。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.讯飞开放平台语音转写…

[图解]实现领域驱动设计译文暴露的问题03

0 00:00:02,960 --> 00:00:04,940 前面我们讲了 1 00:00:05,260 --> 00:00:06,810 第①句话的 2 00:00:07,090 --> 00:00:09,750 第&#xff08;1&#xff09;个问题和第&#xff08;2&#xff09;个问题 3 00:00:13,920 --> 00:00:16,930 共享父类的对象&#…

【软件安装】vmware虚拟机安装完整教程(15.5版本)

安装包-百度网盘&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1zwYeRVdp1TM75JIctkWqVA?pwd6666 提取码&#xff1a;6666 1、去BIOS里修改设置开启虚拟化设备支持&#xff08;这一步必须要进行&#xff09; 网址&#xff1a;https://jingyan.baidu.com/article…

抖音小店怎么运营才能出单呢?就这一个步骤做好,爆单不是梦!

哈喽~我是电商月月 新手做抖音小店绝对会有这两个问题&#xff1a;怎么运营&#xff1f;不出单怎么办&#xff1f;被这两个问题困扰着的商家&#xff0c;别着急&#xff01; 看完我这一篇分享&#xff0c;你就知道自己的问题所在了&#xff01; 抖音小店的运营中&#xff0c…

1070: 邻接矩阵存储简单路径

解法&#xff1a; #include<iostream> #include<vector> using namespace std; int arr[100][100]; int n; int sta, des; vector<int> path; vector<vector<int>> res; void dfs(vector<int> &a,int i) {a[i] 1;path.push_back(i);…

ICode国际青少年编程竞赛- Python-2级训练场-列表遍历

ICode国际青少年编程竞赛- Python-2级训练场-列表遍历 1、 for i in range(3):Flyer[i].step(2) Dev.step(6)2、 for i in range(7):Flyer[i].step() Dev.step(Item.x - Dev.x)3、 for i in range(3):Flyer[i].step(1) Dev.step(4) Dev.turnLeft() Dev.step(2) Dev.turnL…

宝塔环境安装+安装软件教程

游戏&#xff0c;大型网站程序等都安装在服务器上&#xff0c;服务器用的是Linux系统&#xff0c;进行服务器维护需要记住很多linux的命令&#xff0c;这就很麻烦。 宝塔的好处&#xff0c;就是通过一个交互界面就能完成服务器的维护工作&#xff0c;比如更新系统&#xff0c;添…

24.5.12(23广东,19陕西)(字典树)

星期一&#xff1a; dp题单 区间dp第三题 二叉搜索树 cf传送门 思路&#xff1a;dp【i】【j】【0/1】表示区间 i到 j&#xff0c;以 i / j为根节点能否形成一棵二叉搜索树 因为题目要求组成二叉搜索树&#xff0c;若 i 到 j 的节点为一颗完整的子…

信创应用软件之国产邮箱

信创应用软件之国产邮箱 文章目录 信创应用软件之国产邮箱采用信创邮箱的必要性信创邮箱采购需求国产邮箱业务形态国产邮箱代表性品牌CoremailRichmail安宁eyouUMail拓波 邮件安全的发展阶段 采用信创邮箱的必要性 邮箱是天然的数据存储空间&#xff0c;党政和央国企客户在使用…

每日OJ题_贪心算法四⑦_力扣1054. 距离相等的条形码

目录 力扣1054. 距离相等的条形码 解析代码 力扣1054. 距离相等的条形码 1054. 距离相等的条形码 难度 中等 在一个仓库里&#xff0c;有一排条形码&#xff0c;其中第 i 个条形码为 barcodes[i]。 请你重新排列这些条形码&#xff0c;使其中任意两个相邻的条形码不能相等…

十六、Redis和数据库双写一致性问题

众所周知&#xff0c;Redis一般被用来做为数据的缓存中间件&#xff0c;提升系统读数据的能力。但是被缓存的数据并不是一成不变的。如果是永远不会变的&#xff0c;那不会存在双写一致性问题(只需构建一次缓存即可)。但是大部分情况下&#xff0c;或多或少都会涉及到缓存数据的…

发布一下之前的草稿和仅我可见【个人】

发布一下之前的草稿和仅我可见【个人】 前言版权推荐发布一下之前的草稿和仅我可见【个人】java面试面试真题笔试真题 最后 前言 2024-5-13 12:26:55 发布一下之前的草稿和仅我可见 这些一般多事和面试相关的内容 以下内容源自《【创作模板】》 仅供学习交流使用 版权 禁止…

禅道远程安装配置(cpolar)

1. 禅道安装 2. cpolar下载安装 Cpolar的下载可以直接登录cpolar官网&#xff08;www.cpolar.com&#xff09;&#xff0c;下载对应版本即可 download下载 - cpolar 极点云官网 2.1 cpolar官网注册账号 2.2 macOS可以通过brew安装 Cpolar快速入门教程&#xff1a;macOS系列…

16-LINUX--线程安全

一。线程安全 线程安全即就是在多线程运行的时候&#xff0c;不论线程的调度顺序怎样&#xff0c;最终的结果都是 一样的、正确的。那么就说这些线程是安全的。 要保证线程安全需要做到&#xff1a; 1&#xff09; 对线程同步&#xff0c;保证同一时刻只有一个线程访问临界资…

软件3班20240513

java.util.PropertyResourceBundle4554617c package com.yanyu;import java.sql.*; import java.util.ResourceBundle;public class JDBCTest01 {public static void main(String[] args) throws SQLException { // 获取属性配置文件ResourceBundle bundle Res…

【NodeMCU实时天气时钟温湿度项目 3】连接SHT30传感器,获取并显示当前环境温湿度数据(I2C)

今天&#xff0c;我们开始第三个专题&#xff1a;连接SHT30温湿度传感器模块&#xff0c;获取当前环境实时温湿度数据&#xff0c;并显示在1.3寸TFT液晶显示屏上。 第一专题内容&#xff0c;请参考 【NodeMCU实时天气时钟温湿度项目 1】连接点亮SPI-TFT屏幕和UI布局设计…

8个手机宝藏App,建议收藏!

AI故事视频生成&#xff0c;一站式生成小说漫画推文、儿童故事、民间故事等https://aitools.jurilu.com/ 1.地图车机版——百度地图 百度地图&#xff0c;作为新一代的人工智能地图&#xff0c;以其智能语音、智能导航系统、智能路线规划和智能推荐方案而著称。它不仅提供传统…