题目:
恶魔猎手尤迪安野心勃勃.他背叛了暗夜精灵,率深藏在海底的那加企图叛变:守望者在与尤迪安的交锋中遭遇了围杀.被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去,到那时,岛上的所有人都会遇难:守望者的跑步速度,为17m/s,以这样的速度是无法逃离荒岛的。庆幸的是守望者拥有闪烁法术,可在1s内移动60m,不过每次使用闪烁法术都会消耗魔法值10点。守望者的魔法值恢复的速度为4点/s,只有处在原地休息状态时才能恢复。
现在已知守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。你的任务是写一个程序帮助守望者计算如何在最短的时间内逃离荒岛,若不能逃出,则输出守望者在剩下的时间内能走的最远距离。注意:守望者跑步、闪烁或休息活动均以秒(s)为单位。且每次活动的持续时间为整数秒。距离的单位为米(m)。
1 <= t <= 300000, 0 <= m<=1000 1 <=s <= 10^8
解题思路:(动态规划+滚动数组)
每一秒的选择只能有三种(走路,闪烁,回蓝),所以按照时间来动规
f[i,j]表示第i秒最多使用j点魔法值跑的最远距离
f[i,j]=max{f[i-1][j]+17(走路),f[i-1][j-10]+60(闪烁),f[i-1][j+4](回蓝)}
回蓝可以理解为前i秒中某一秒用来回蓝,这一秒用来闪烁或者走路能走的最远距离
package huawei;
/*
功能:判断守望者是否能够逃出荒岛
输入参数:
int uiMagic:整型,守望者的初始魔法值
int uiDistance:整型,守望者所在的初始位置与岛出口之间的距离。
int uiSec:整型,岛沉没需要的时间,单位为秒
StringBuilder pRstOut:保证传入的是空的StringBuilder对象,要求把结果加入,输出守望者能否逃出荒岛,若能逃出输出“Yes”,不能输出“No”,注意大小写。
返回值:
若守望者能逃出荒岛,输出逃出荒岛所用的最短时间,
不能逃出则输出守望者能逃出的最大距离。
*/
public class Demo
{
private int[][] dp=new int[2][1005];
private void Initial()
{
for(int i=0;i<2;i++)
{
for(int j=0;j<1005;j++)
dp[i][j]=0;
}
}
public int helpWatcherEscape(int uiMagic, int uiDistance, int uiSec,
StringBuilder pRstOut)
{
Initial();
boolean EscapeSucceed=false;
int i,flag=1;
for(i=1;i<=uiSec;i++)
{
int max=-1;
for(int j=0;j<=uiMagic;j++)
{
int now=1-flag;
if(max<dp[now][j]+17)
max=dp[now][j]+17;
if(j>=10&&max<dp[now][j-10]+60)
max=dp[now][j-10]+60;
if(j>=4&&max<dp[now][j+4])
max=dp[now][j+4];
dp[flag][j]=max;
if(dp[flag][j]>=uiDistance)
{
EscapeSucceed=true;
break;
}
}
flag=1-flag;
if(EscapeSucceed)
break;
}
if(pRstOut==null)
pRstOut=new StringBuilder();
if(EscapeSucceed)
{
pRstOut.append("Yes");
return i;
}
else
{
pRstOut.append("No");
return dp[uiSec&1][uiMagic];
}
}
}