题目描述
小青蛙住在一条河边,它想到河对岸的学校去学习。小青蛙打算经过河里的石头跳到对岸。
河里的石头排成了一条直线,小青蛙每次跳跃必须落在一块石头或者岸上。不过,每块石头有一个高度,每次小青蛙从一块石头起跳,这块石头的高度就会下降 1,当石头的高度下降到 0 时小青蛙不能再跳到这块石头上(某次跳跃后使石头高度下降到 0 是允许的)。
小青蛙一共需要去学校上 x 天课,所以它需要往返 2x 次。当小青蛙具有一个跳跃能力 y 时,它能跳不超过 y 的距离。
请问小青蛙的跳跃能力至少是多少才能用这些石头上完 x 次课。
输入格式
输入的第一行包含两个整数 n, x,分别表示河的宽度和小青蛙需要去学校的天数。请注意 2x 才是实际过河的次数。
第二行包含 n − 1 个非负整数 H1, H2, · · · , Hn-1,其中 Hi > 0 表示在河中与小青蛙的家相距 i 的地方有一块高度为 Hi 的石头,Hi = 0 表示这个位置没有石头。
输出格式
输出一行,包含一个整数,表示小青蛙需要的最低跳跃能力。
样例输入
复制
5 1 1 0 1 0
样例输出
复制
4
提示
由于只有两块高度为 1 的石头,所以往返只能各用一块。第 1 块石头和对岸的距离为 4,如果小青蛙的跳跃能力为 3 则无法满足要求。所以小青蛙最少需要 4 的跳跃能力。
对于 30% 的评测用例,n ≤ 100;
对于 60% 的评测用例,n ≤ 1000;
对于所有评测用例,1 ≤ n ≤ 105 , 1 ≤ x ≤ 109 , 1 ≤ Hi ≤ 104。
使用回溯算法,运行超时。从最远处i可跳的石头起跳,若不能跳再尝试i-1,i-2,...回溯递归,使用temp记录当前跳法的最远跳跃距离,若temp>jump_max 则结束当前跳法,jump_max记录不同跳法情况下需要的最小的跳跃能力
此方法运算时间太长
import java.util.*;
public class Main{
static int n;
static int x;
static int H[];
static int jump_max;
public static void dfs(int temp,int t,int layer)//t表示第t个石头,layer表示第几次跳,temp保存本次跳跃的距离
{ //if(total<2*x-layer) return;//设置total作为回溯条件之一
if(temp>jump_max) return;
if(t==n)
{
dfs(temp,0,layer+1);//进入下一层
return;
}
if(layer==2*x)
{
if(temp<jump_max) jump_max=temp;
return;
}
int mid,q;
q=temp;
for(int i=n;i>=t+1;i--)
{
if(H[i]>0)
{ H[i]--;
mid=i-t;
if(mid>temp) temp=mid;
dfs(temp,i,layer);
temp=q;
H[i]++;
}
}
}
public static void main(String args[])
{
Scanner in=new Scanner(System.in);
n=in.nextInt();
x=in.nextInt();
H=new int[n+1];
H[0]=2*x;H[n]=2*x;
jump_max=n;
int total=0;
for(int i=1;i<=n-1;i++)
{ H[i]=in.nextInt();
total+=H[i];
}
if(total<2*x) jump_max=n;
else dfs(0,0,0);
System.out.println(jump_max);
}
}