題目描述
在河上有一座獨木橋,一只青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由于橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點:0,1,……,L(其中L是橋的長度)。坐標為0的點表示橋的起點,坐標為L的點表示橋的終點。青蛙從橋的起點開始,不停的向終點方向跳躍。一次跳躍的距離是S到T之間的任意正整數(包括S,T)。當青蛙跳到或跳過坐標為L的點時,就算青蛙已經跳出了獨木橋。
題目給出獨木橋的長度L,青蛙跳躍的距離范圍S,T,橋上石子的位置。你的任務是確定青蛙要想過河,最少需要踩到的石子數。
對于30%的數據,L?<=?10000;對于全部的數據,L?<=?10^9。<=?10^9<=?10^9<=?10^9<=?10^9<=?10^9<=?10^9=?10^9
輸入
輸入的第一行有一個正整數L(1?<=?l?<=?10^9),表示獨木橋的長度。第二行有三個正整數S,T,M,分別表示青蛙一次跳躍的最小距離,最大距離,及橋上石子的個數,其中1?<=?s?<=?t?<=?10,1?<=?m?<=?100。第三行有M個不同的正整數分別表示這M個石子在數軸上的位置(數據保證橋的起點和終點處沒有石子)。所有相鄰的整數之間用一個空格隔開。<=?m?<=?100<=?m?<=?100<=?m?<=?100<=?m?<=?100<=?m?<=?100<=?m?<=?100=?M?<=?100
問題算法本身不難,一個從后往前反向求出起點最小石子個數的動態規劃問題,搜索青蛙過河,網上可以找到很多帖子。不過只這么做是不夠的,首先數據量大的時候,內存直接爆了,所以需要壓縮數據,片段化處理;另一個就是一個特殊情況,如果青蛙最小步數和最大步數相等時,直接計算即可。
這里主要記錄下我自己是怎么壓縮的,思路主要是這樣,首先對石子位置進行排序,然后從后往前遍歷,如果發現兩個石子之間距離過長,那么就以后一個石子為開頭得到一個片段;然后計算經過這個片段的最小石子個數。最終整個獨木橋的最小石子個數,就是所有片段結果之和。
那么現在的問題就是,怎么才算石子之間的距離足夠長。如果前maxStep個數已經都一樣了,那么再怎么往前推,都是一個數了;而多長的距離能夠保證前面的數都變成最小值,我的想法比較簡單粗暴,跟冒泡排序的想法有點接近,就是假設最后一個值(maxStep-1位置上的值)是最小值,那么它每一輪往前移動(maxStep-minStep)個位置,直接假定每一輪的長度為maxStep,所以它移動到第一個位置需要(maxStep - 1)*maxStep/(maxStep-minStep)。所以,如果兩個石子之間的距離超過這個值,那么直接算出這個片段每個位置的最小石子數,然后取前面maxStep個值的最小值。
最后,如果到了最開始的片段,如果第一個石子離起點還是足夠遠,可以一樣計算,但是,如果第一個石子離起點很近的時候,直接計算到起點的最小石子數即可。