华为校招笔试:洞穴逃生

题目

原文

精灵王子爱好冒险,在一次探险历程中,他进入了一个神秘的山洞。在洞穴深处,精灵王子不小心触动了洞穴内暗藏的机关,整个洞穴很快塌陷,精灵王子必须晶块逃离洞穴。精灵王子的跑步速度为17m/s,以这样的速度可能是无法逃出洞穴的。庆幸的是精灵王子拥有闪烁法术,可在1s内移动60m,不过每次使用闪烁法术都会消耗魔法值10点。精灵王子的魔法值恢复的速度为4点/s,只有处在原地休息状态时才能恢复。
现在已知精灵王子的魔法初始值M,他所在洞穴中的位置与洞口出口之间的距离S,距离洞穴坍塌的时间T。你的任务是写一个程序帮助精灵王子计算如何在最短的时间内逃离洞穴。若能逃出,输出”Yes”,并输出逃出所有的最短时间;若不能逃出,则输出”No”,同时输出精灵王子在剩下的时间内能走的最远距离。注意字母大小写。注意:精灵王子跑步、闪烁或休息活动均以秒(s)为单位。且每次活动的持续时间为整数秒。距离的单位(m)。

分析

一眼望过去都是密密麻麻的文字,看着很吓人。没关系,我们把对我们有用的信息提炼出来就好了:

  • 跑步速度:17m/s,闪烁速度:60m/s
  • 闪烁需要消耗10点魔法值,魔法值的恢复速度为4点/s,恢复时需要在原地休息
  • 秒(s)为原子单位,也就是说不存在零点几秒

通过分析我们可以得出:

  • 如果魔法充足,优先使用闪烁
  • 如果魔法不足,则分情况考虑(如下表):
    • 如果距离 >= 60m且 <= 68m,跑步更划算
    • 如果距离 <= 34m,跑步更划算
    • 其他情况则闪烁更划算
      距离=34,60m时,跑步和闪烁是等效的(都能逃出洞口),为了简化问题,统一使用跑步。
      
魔法值 闪烁 跑步
0、1 (3+1)s - 60m 4s - 68m
2、3、4、5 (2+1)s - 60m 3s - 51m
6、7、8、9 (1+1)s - 60m 2s - 34m
1s - 17m
使用闪烁需要的时间 = 恢复时间 + 使用时间

参考答案

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int m, s, t;
Scanner cin = new Scanner(System.in);
m = cin.nextInt();
s = cin.nextInt();
t = cin.nextInt();
Main test = new Main();
test.start(m, s, t);
}
public void start(int m, int s, int t) {
//记录初始距离
int l = s;
int second = 0;
while (s > 0) {
//如果魔法大于10 就使用魔法
while (m >= 10) {
second++;
if (second > t) {
System.out.println("No " + (l - s));
return;
}
m -= 10;
s -= 60;
if (s <= 0) {
System.out.println("Yes " + second);
return;
}
}
//跑
if (s >= 60 && s <= 68) {
second += 4;
if (second > t) {
System.out.println("No " + (l - s));
return;
}
s -= 17 * 4;
} else if (s <= 34) {
second++;
if (second > t) {
System.out.println("No " + (l - s));
return;
}
s -= 17;
} else {
//休息
int tem = 0;
while (m < 10) {
second++;
//尝试跑
tem += 17;
if (second >= t) {
System.out.println("No " + ((l - s) + tem));
return;
}
if (tem > s){
System.out.println("Yes " + second);
return;
}
m += 4;
}
}
}
System.out.println("Yes " + second);
}
}