题目
张三购买了一辆续航里程数达 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();
}
}