赞
踩
华为OD机试 2024C卷题库疯狂收录中,刷题点这里
本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷+C卷)》。
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。
孙悟空喜欢吃蟠桃,一天他乘守卫蟠桃园的天兵天将离开了而偷偷的来到王母娘娘的蟠桃园偷吃蟠桃。
已知蟠桃园有 N 棵蟠桃树,第 i 棵蟠桃树上有 N[i](大于 0)个蟠桃,天兵天将将在 H(不小于蟠桃树棵数)小时后回来。
孙悟空可以决定他吃蟠桃的速度 K(单位:个/小时),每个小时他会选择一颗蟠桃树,从中吃掉 K 个蟠桃,如果这棵树上的蟠桃数小于 K,他将吃掉这棵树上所有蟠桃,然后这一小时内不再吃其余蟠桃树上的蟠桃。
孙悟空喜欢慢慢吃,但仍想在天兵天将回来前将所有蟠桃吃完。
求孙悟空可以在 H 小时内吃掉所有蟠桃的最小速度 K(K 为整数)。
从标准输入中读取一行数字,前面数字表示每棵数上蟠桃个数,最后的数字表示天兵天将将离开的时间。
吃掉所有蟠桃的 最小速度 K(K 为整数)或 输入异常时输出 -1。
3 11 6 7 8
4
天兵天将8个小时后回来,孙悟空吃掉所有蟠桃的最小速度4。
题目描述有点复杂,多读几遍不难理解,意思就是:
一个小时只能在一棵桃树上吃,如果吃不完,下一个小时继续吃,如果吃完了,就不吃了,但不能去吃下一颗桃树,要守规矩。
很明显的回溯问题,一个一个找呗,看哪个速度最合适。
假如孙猴子一小时吃100个桃子最合适,效率有点堪忧。
public class Test06 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[] arr = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray(); // 天兵天将将离开的时间H int H = arr[arr.length - 1]; // 获取每棵数上蟠桃个数 arr = Arrays.copyOf(arr, arr.length - 1); // 从少到多排序 Arrays.sort(arr); // 从速度1开始回溯,寻找H小时内吃完所有桃子的最小速度 dfs(arr, H, 1); System.out.println(minSpeed); System.out.println("执行次数:" + num); } // 记录回溯次数,优化回溯算法 static int num = 0; // 吃完所有桃子的最小速度 static int minSpeed = 0; /** * 从速度1开始回溯,寻找H小时内吃完所有桃子的最小速度 */ private static void dfs(int[] arr, int H, int K) { int times = 0; for (int i = 0; i < arr.length; i++) { num++; // 以速度K吃完每颗桃树的时间 times += arr[i] / K; if (arr[i] % K != 0) { times++; } } // 因为速度从小到大递增,当时间 <= H时,即最小速度 if (times <= H) { minSpeed = K; return; } else { // 吃不完,加快速度 dfs(arr, H, ++K); } } }
输入:3 25 6 7 8
输出:7
执行次数:28
所有桃子的数量除以总时间,得出每小时吃桃子数量,我觉得这个就是比较接近最小速度的最优解。
public class Test08 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[] arr = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray(); // 天兵天将将离开的时间H int H = arr[arr.length - 1]; // 获取每棵数上蟠桃个数 arr = Arrays.copyOf(arr, arr.length - 1); // 从少到多排序 Arrays.sort(arr); // 预测最可能速度,优化回溯算法 int sum = Arrays.stream(arr).sum(); int possible = sum % H == 0 ? sum / H : sum / H + 1; System.out.println("预测最可能速度:" + possible); // 从最可能速度开始回溯,寻找H小时内吃完所有桃子的最小速度 dfs(arr, H, possible); System.out.println(minSpeed); System.out.println("执行次数:" + num); } // 记录回溯次数,优化回溯算法 static int num = 0; // 吃完所有桃子的最小速度 static int minSpeed = 0; // 上一次吃完所有桃子的速度 static int preSpeed = 0; private static void dfs(int[] arr, int H, int K) { int times = 0; for (int i = 0; i < arr.length; i++) { num++; // 以速度K吃完每颗桃树的时间 times += arr[i] / K; if (arr[i] % K != 0) { times++; } } // 吃不完,加快速度 if (times > H) { // 如果上次已经吃完,则上次吃完的速度即最小速度 if (preSpeed != 0) { minSpeed = preSpeed; return; } dfs(arr, H, ++K); } else if (times < H) {// 吃完了,再吃慢一点 preSpeed = K; dfs(arr, H, --K); } else {// 刚好吃完,返回最小速度 minSpeed = K; return; } } }
输入:3 25 6 7 8
输出:7
预测最可能速度:6
执行次数:12
public class Test09 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[] arr = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray(); // 天兵天将将离开的时间H int H = arr[arr.length - 1]; // 获取每棵数上蟠桃个数 arr = Arrays.copyOf(arr, arr.length - 1); // 从少到多排序 Arrays.sort(arr); int left = 1; int right = arr[arr.length - 1]; while (left < right) { int mid = (left + right) / 2; // 吃完了,还能慢一点 if (dfs(arr, H, mid)) { right = mid; } else {// 没吃完,吃快一点 left = mid + 1; } } System.out.println(left); System.out.println("执行次数:" + num); } // 记录回溯次数,优化回溯算法 static int num = 0; // 上一次吃完所有桃子的速度 static int preSpeed = 0; private static boolean dfs(int[] arr, int H, int K) { int times = 0; for (int i = 0; i < arr.length; i++) { num++; // 以速度K吃完每颗桃树的时间 times += arr[i] / K; if (arr[i] % K != 0) { times++; } } return times <= H; } }
输入:3 25 6 7 8
输出:7
执行次数:16
通过对比,还是预测一个最可能的速度效率最高,嘿嘿~
3 25 6 7 8
7
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。