在河上有一座獨木橋,一隻青蛙想沿着獨木橋從河的一側跳到另外一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。因爲橋的長度和青蛙一次跳過的距離都是正整數,咱們能夠把獨木橋上青蛙可能到達的點當作數軸上的一串整點:0,1,……,L(其中L是橋的長度)。座標爲0的點表示橋的起點,座標爲L的點表示橋的終點。青蛙從橋的起點開始,不停的向終點方向跳躍。一次跳躍的距離是s到t之間的任意正整數(包括s,t)。當青蛙跳到或跳過座標爲L的點時,就算青蛙已經跳出了獨木橋。
題目給出獨木橋的長度L,青蛙跳躍的距離範圍s,t,橋上石子的位置。你的任務是肯定青蛙要想過河,最少須要踩到的石子數。ios
Inputide
有多組測試數據。
對於每組測試數據,第一行四個正整數L, s, t, n(1 <= L <= 10^5, 1 <= s <= t <= 10,1 <= n <= 100),分別表示獨木橋的長度,青蛙一次跳躍的最小距離,最大距離,及橋上石子的個數。第二行有n個不一樣的正整數分別表示這n個石子在數軸上的位置(數據保證橋的起點和終點處沒有石子)。全部相鄰的整數之間用一個空格隔開。測試
Outputspa
每組測試數據僅輸出一行,包括一個整數,表示青蛙過河最少須要踩到的石子數。code
題解:blog
顯然是一個動態規劃的題目,可是和我想的不太同樣,ci
本來思路是 :以到達石子 i 所在位置所須要踩到的石子數,創建一個2維的表格,開始遞推打表就行,發現寫不出來根本無法斷定。博客
錯因:子問題找錯了,及動態規劃最重要的 divide and conquer (DAC)出錯;string
參照了博客後發現本身的思路不太對,應該直接枚舉青蛙可能到達的全部位置,狀態轉移方程式:dp[i]=min(dp[i], dp[i+j]),dp[i]是指從終點(不肯定)到達i點的cost,找到這個思路後發現這個和數塔那個題目很類似,io
數塔是從多個終點推到起點(不過有2個變量x,y座標),這個也是從多個終點推到一個起點(只有一個變量x,可是題目給了一個範圍致使x還要隨跳躍的距離而變化,這樣又變成了很類似數塔題目,那又是一道模板題,居然以前不會寫 Orz.....)
反思:
這種不是很複雜的dp問題,注意好本身的思路,以什麼爲狀態進行轉移,而後開始遞推(相似打表);
1 #include <iostream> 2 #include <cstring> 3 #define min(x,y) ((x)>(y)?(y):(x)) 4 using namespace std; 5 6 const int maxn=1e5+20; 7 const int INF=0x3f3f3f3f; 8 9 int main () 10 { 11 int dp[maxn]={0},vis[maxn]={0}; 12 int l,s,t,n; 13 while(cin>>l>>s>>t>>n) 14 { 15 memset(dp, 0, sizeof(dp)); 16 memset(vis, 0, sizeof(vis)); 17 for(int i=0; i<n; i++) 18 { 19 int date; cin>>date; 20 vis[date]=1; 21 } 22 23 for(int i=l-1; i>=0; i--) 24 { 25 dp[i]=INF; 26 for(int j=s; j<=t; j++) 27 dp[i]=min(dp[i],dp[i+j]); 28 dp[i]+=vis[i]; 29 } 30 cout<<dp[0]<<endl; 31 } 32 return 0; 33 }