算法:DP。
如果数据不是很大的话我们就可以直接DP了...
但是数据有 10^9,所以普通的DP根本不能AC.
我记得一个月以前我做了这道题目,普通地DP,然后只能过三个点。
数组不能开这么大,就算能开这么大也会超时。
这里有个路径压缩的优化方法。。。。(纯属装B....)
首先我们先分析一下数据规模,我们发现呢,L<=10^9. 而石子的个数m<=100.
这就意味着平均两个石子中间有10^7 的路是没有石子的。
也就是说,两个石子中间我们进行了很多没有必要的DP。
我们可以稍微把中间给缩减一下。
我们通过一个运算求得一次最短可跳长度(S)到一次最长可跳长度(T)中的每一个数的最小公倍数的值为k。
假如青蛙可以跳到i点,那么很容易地,他一定能够跳到第k+i点。
设有两个石子,ss[i] 和 ss[i+1]. ss表示石子的坐标。
如果我们有 ss[i+1]-ss[i]>k 的话,因为中间我们走的地方都是没有石子的,我们可以把他们之间的距离缩短一下,缩短成 ss[i+1]-ss[i]-a*k.(如果他们之差是k的倍数,a=(差 div k)-1,
如果不是,a=差 div k)。这样我们就把它们的距离缩短了,但是这个过程不会影响最终的结果。
同理,将每一个点都进行路径压缩,之后就可以像普通DP一样了(PS.看了网上的题解,据说k=100可以应对s<>t的所有情况,我试过的确如此,但是不知道如何证明,所以我还是用了最
小公倍数的方法)。
代码:
1 program p1002; 2 var 3 s,t,t1,i,j,k,l,m,n,a,b,ans:longint; 4 f:array[-100..120000]of longint; 5 ss:array[0..11000]of longint; 6 boo:array[0..11000]of boolean; 7 d:array[0..10000]of longint; 8 function min(a,b:longint):longint; 9 begin 10 if a0)or(b mod j<>0); 26 dec(j); 27 a:=j*(a div j)*(b div j); 28 end; 29 k:=a; 30 if k=t then k:=100; 31 for i:=1 to n do 32 read(ss[i]); 33 for i:=2 to n do 34 for j:=1 to i-1 do 35 if ss[i]k then 44 begin 45 if(ss[i]-ss[i-1]) mod k<>0 then 46 a:=(ss[i]-ss[i-1])div k 47 else a:=(ss[i]-ss[i-1])div k-1; 48 for j:=i to n do 49 ss[j]:=ss[j]-a*k; 50 l:=l-a*k; 51 end; 52 end; 53 if l-ss[n]>k then 54 begin 55 if (l-ss[n]) mod k<>0 then 56 a:=(l-ss[n])div k 57 else a:=(l-ss[n])div k-1; 58 l:=l-a*k; 59 end; 60 filldword(f,sizeof(f) div 4,maxlongint div 2); 61 fillchar(d,sizeof(d),0); 62 for i:=1 to n do 63 d[ss[i]]:=1; 64 for i:=-20 to s-1 do f[i]:=-1; 65 f[0]:=0; 66 for i:=s to t do 67 f[i]:=d[i]; 68 for i:=s to l+t-1 do 69 begin 70 for j:=s to t do 71 begin 72 if f[i-j]<>-1 then 73 f[i]:=min(f[i],f[i-j]+d[i]); 74 end; 75 end; 76 ans:=maxlongint; 77 for i:=l downto l-s+1 do 78 ans:=min(ans,f[i]); 79 while f[l]>=maxlongint div 2 do dec(l); 80 write(ans); 81 close(input); 82 end.