JZOJ 4.8 2016——最小步数【记忆化搜索】
Description
从起点到终点有N步,如果“走”第K步,将会得到A[K]元钱,A[K]可能为负数。
你也可以花100元钱“跳过”当前的这一步,即不会得到A[K]。但是任何时刻身上的钱都必须是非负的。开始时,你身上共有0元。给定数组A,求在能到达终点的情况下最小需要走过(即不是用100元钱跳过)的步数。注意:最后一步必须走,不能选择跳过。
Input
共有两行。
第一行为整数N(0<=N<=100)。
第二行有N个整数,第K个数为A[K],-10000<=A[K]<=10000,。
Output
一个整数,表示需要走的最少步数。若无法走到终点,输出-1。
Sample Input
6
30 30 30 30 30 30
Sample Output
5
记忆化搜索+剪枝
剪枝:
①如果当前已经等于最小步数,退出
②如果当前剩下的费用比原来还小,退出
然后赋值
最后跳和走两种情况搜索
代码如下:
var n,i,min:longint;
f:array[0..101,0..101]of longint;
a:array[0..101]of longint;
procedure search(i,j,s:longint);
begin
if (s+1>=min)or(j<=f[i,s]) then exit;
f[i,s]:=j;
if (i=n) then begin if(j+a[i]>=0)and(s+1<min) then min:=s+1; exit; end;
if (j-100>=0) then search(i+1,j-100,s);
if (j+a[i]>=0) then search(i+1,j+a[i],s+1);
end;
begin
readln(n);
for i:=1 to n do read(a[i]);
fillchar(f,sizeof(f),255);
min:=maxlongint;
search(1,0,0);
if min=maxlongint then write(-1) else write(min);
end.