华为机试题-充电规划

文章讨论了如何使用动态规划方法为一辆续航里程达1000公里的自动驾驶新能源车规划从甲城到乙城的最短行驶时间,考虑到沿途休息站的充电排队时间。通过计算,找到在最少休息站充电以达到最小总耗时的策略。
摘要由CSDN通过智能技术生成
题目

张三购买了一辆续航里程数达 1000 公里的某自动驾驶新能源车。
某天车辆充满电后,需从甲城出发前往距离 D 公里远的乙城,全程走高速。
车载导航提示沿途有 N 个休息站均可提供充电服务,各休息站均可实时提供当
前充电排队时间(小时)。
请协助规划时间最优的休息站充电方案,返回最短的旅行用时。
为方便计算,高速上的行驶速度固定为 100 公里/小时。
规划时可不必考虑保留安全续航里程数,汽车可以将电完全用光,1000 公里续航
的汽车
按 100 公里/小时,可以开 10 个小时。
每次充电时间固定为 1 小时,完成后电量充满。
各站点充电排队时间不会变化,充电排队过程不耗电。
解答要求
时间限制:C/C++1000ms,其他语言:2000ms
内存限制:C/C++ 256MB,其他语言:512MB
输入
第一行表示甲乙两城的距离 D,单位为公里;第二行表示沿途的休息站数量 N;
第三行起,每行 2 个数据,分别表示休息站距离甲城的距离,以及充电排队所需时
间(小时),(各休息站按距离从近到远排序)
0<=D<=1000000, D 是 100 的整数倍 0<=N=10000
样例 1
输入:
1500
4
300 2
600 1
1000 0
1200 0
输出:16
解释:最佳方案:只在第 3 个休息站(位置 1000)进行充电
1500 公里的行程耗时:15 小时
充电排队 0 小时,充电 1 小时最快旅程总计花费 16 小时
其他方案:在第 2 个休息站(位置 600)进行充电,总计花费 17 小时
其他方案:在第 2 个休息站(位置 600)和第 4 个休息站(位置 1200)进行充电,总计
花费 19 小时
样例 2
输入:
800
2
300 0
600 0
输出:8
解释:最佳方案:不进任何休息站充电
800 公里的行程耗时:8 小时

参考代码

动态规划的思想

package RealTest;

/**
 * @ClassName chargePlan
 * @Description TODO
 * @Author 21916
 * @Date 2024/3/13 21:42
 */

import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;

public class chargePlan {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // d 公里数,是100的倍数
        // n 休息站的数量
        int d = Integer.parseInt(scanner.nextLine());
        int n = Integer.parseInt(scanner.nextLine());

        // lst 存储充电站的坐标和等待时间,这里将甲地也当作一个充电站,甲地坐标为0
        List<List<Integer>> lst = new ArrayList<>();
        lst.add(List.of(0, 0));

        // 输入n个充电站数据
        for (int i = 1; i <= n; i++) {
            List<Integer> station = new ArrayList<>();
            String[] input = scanner.nextLine().split("\\s+");
            for (String s : input) {
                station.add(Integer.parseInt(s));
            }
            lst.add(station);
        }

        // 将乙地也当作一个充电站
        lst.add(List.of(d, 0));

        // dp 数组 dp[i] 表示到达第i号充电站并在第i个充电站充电后花费的最短充电时间
        List<Integer> dp = new ArrayList<>();
        dp.add(0);

        // 遍历第1~n+1号充电站,我们把乙地当作n+1号充电站
        for (int i = 1; i <= n + 1; i++) {
            int site = lst.get(i).get(0);
            int time = lst.get(i).get(1);

            // 一开始设置一个大点的数
            dp.add(Integer.MAX_VALUE);

            // 从后向前找相邻的充电站
            for (int j = i - 1; j >= 0; j--) {
                int a_site = lst.get(j).get(0);
                int a_time = lst.get(j).get(1);

                // 第i个充电站和第j个充电站的距离大于1000km则说明 【从j充电站充满电后不能直接到i充电站】
                if (site - a_site > 1000) {
                    break;
                } else {
                    dp.set(i, Math.min(dp.get(i), dp.get(j) + time + 1));
                }
            }

            // 如果dp[i]没有被更新,说明不能从前面的任何一个充电站到第i个充电站,终点不可达
            if (dp.get(i) == Integer.MAX_VALUE) {
                System.out.println(-1);
                System.exit(0);
            }
        }

        // 因为沿途的距离是固定的,所以直接加上就行,减1是因为之前将乙地当作一个充电站,充电花费的1h要减掉
        System.out.println(dp.get(n + 1) + d / 100 - 1);

        scanner.close();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@业精于勤荒于嬉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值