恶魔猎手尤迪安野心勃勃.他背叛了暗夜精灵,率深藏在海底的那加企图叛变:守望者在与尤迪安的交锋中遭遇了围杀.被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去,到那时,岛上的所有人都会遇难:守望者的跑步速度,为17m/s,以这样的速度是无法逃离荒岛的。庆幸的是守望者拥有闪烁法术,可在1s内移动60m,不过每次使用闪烁法术都会消耗魔法值10点。守望者的魔法值恢复的速度为4点/s,只有处在原地休息状态时才能恢复。
现在已知守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。你的任务是写一个程序帮助守望者计算如何在最短的时间内逃离荒岛,若不能逃出,则输出守望者在剩下的时间内能走的最远距离。注意:守望者跑步、闪烁或休息活动均以秒(s)为单位。且每次活动的持续时间为整数秒。距离的单位为米(m)。
来源:http://eden.sysu.edu.cn:8080/m/ass/702/
递归+回溯
(无法计算剩余的时间和最小距离,但可以判断是否能够走出,但会超时)
#include <stdio.h>
int flag = 0;
void watcher(int time, int magic, int dis) {
if (dis <= 0 && time >= 0) {
flag = 1;
return;
}
if (time <= 0) {
return;
} else {
watcher(time - 1, magic, dis - 17);
if (magic >= 10) {
watcher(time - 1, magic - 10, dis - 60);
}
watcher(time - 1, magic + 4, dis);
}
}
int main () {
int N;
scanf("%d", &N);
while (N--) {
int n, m, t;
scanf("%d%d%d", &n, &m, &t);
watcher(t, n, m);
if (flag) {
printf("YES\n");
} else {
printf("NO\n");
}
}
return 0;
}
分析:
主体思想:先狂用闪烁,魔法不够了再根据时间、魔法值和距离来判断下一步是跑步还是恢复魔法值后闪烁。
思考后得出了一个用光魔法后由时间、魔法、距离的关系所做的决策。
http://www.bubuko.com/infodetail-109262.html
由上表格,就可以使用范围判断法来确定决策了。
解释:例如,当魔法值是0或1时,如要闪烁一次需恢复3秒,加上闪烁时间共4秒,才跑60m,而跑步就可以跑17×4=68m了。因此,如在时间足够的前提下,恢复5秒闪烁2次,共花费7秒,跑了60×2=120m,而跑步只能跑17×7=119m。因此,在条件允许的情况下,所作决策为恢复+闪烁。至于距离剩余的条件,大家可以想一下,当前的剩余距离如果并不需要使用恢复+闪烁,而可以用更少的时间用跑步来完成,那当然用跑步好啦!当剩余距离不大于102时,跑步最多只需花102÷17=6(秒),而不需要再用7秒了。
魔法值剩余2~9的决策和条件原因同上。
此题用贪心需要考虑的一些点
1. 当开始狂用闪烁时如果魔法值还足够可是已经跑完了就会错误。
2. 同样,狂用闪烁时如果时间不够闪烁了也会错误。
3. 上面讲过了,剩余距离无需恢复+闪烁只需跑步的情况也要考虑到。
考虑到以上几点就可以开始写代码了。
#include <stdio.h>
void escape(int magic, int space, int timeleft) {
int spaceelse = 0, timeleftelse = timeleft;
while (magic >= 10 && timeleft > 0 && space - spaceelse > 0) {
if (space - spaceelse > 17) {
spaceelse += 60;
magic -= 10;
timeleft--;
} else {
printf("Yes\n%d\n", timeleftelse - timeleft + 1);
}
}
while (timeleft > 0 && space - spaceelse > 0) {
if ((magic == 0 || magic == 1) &&
timeleft >= 7 && space - spaceelse > 102) {
timeleft -= 7;
spaceelse += 120;
} else if (magic >= 2 && magic <= 5 &&
timeleft >= 3 && space - spaceelse > 34) {
magic -= 2;
timeleft -= 3;
spaceelse += 60;
} else if (magic >= 6 && timeleft >= 2 &&
space - spaceelse > 17) {
magic -= 6;
timeleft -= 2;
spaceelse += 60;
} else {
spaceelse += 17;
timeleft--;
}
}
if (space <= spaceelse) {
printf("Yes\n%d\n", timeleftelse - timeleft);
} else {
printf("No\n%d\n", spaceelse);
}
return;
}
int main() {
int N;
scanf("%d", &N);
while (N--) {
int n, m, t;
scanf("%d%d%d", &n, &m, &t);
escape(n, m, t);
}
return 0;
}