哈理工訓練賽 青蛙過河 dp

題目:

在河上有一座獨木橋,一隻青蛙想沿着獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點:0,1,……,L(其中L是橋的長度)。座標爲0的點表示橋的起點,座標爲L的點表示橋的終點。青蛙從橋的起點開始,不停的向終點方向跳躍。一次跳躍的距離是s到t之間的任意正整數(包括s,t)。當青蛙跳到或跳過座標爲L的點時,就算青蛙已經跳出了獨木橋。


題目給出獨木橋的長度L,青蛙跳躍的距離範圍s,t,橋上石子的位置。你的任務是確定青蛙要想過河,最少需要踩到的石子數。 Input有多組測試數據。
對於每組測試數據,第一行四個正整數L, s, t, n(1 <= L <= 10^5, 1 <= s <= t <= 10,1 <= n <= 100),分別表示獨木橋的長度,青蛙一次跳躍的最小距離,最大距離,及橋上石子的個數。第二行有n個不同的正整數分別表示這n個石子在數軸上的位置(數據保證橋的起點和終點處沒有石子)。所有相鄰的整數之間用一個空格隔開。 Output每組測試數據僅輸出一行,包括一個整數,表示青蛙過河最少需要踩到的石子數。 Sample Input10 2 3 5
2 3 5 6 7 Sample Output2題意:

尋找青蛙最後踩到的最少的石頭;

分析:

這裏應該很容易想到dp,代碼量也非常的簡短,但是這裏有一個非常坑的點,也是這個點讓我卡了兩個小時,所以現在決定把它記錄下來。就是dp的終點,很自然的想到是l點,但是題目上說了,當青蛙跳到或跳過l點都視作青蛙跳到了終點,所以dp的終點應該是l到l+t,這樣就產生了一個範圍,所以最終最小值還要取一下最小。這個地方真的是有坑了,注意到這裏就沒有問題了。

代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
const int maxed=100000+20;
int dp[maxed],p[maxed],l,s,t,n;
int main()
{
    while(scanf("%d%d%d%d",&l,&s,&t,&n)!=EOF){
        memset(p,0,sizeof(p));
        memset(dp,INF,sizeof(dp));
        int a;
        for(int i=0;i<n;i++){
            scanf("%d",&a);
            p[a]=1;
        }
        dp[0]=0;
        for(int i=1;i<=l+t;i++){
            for(int j=s;j<=t;j++)
                if(i-j>=0)
                    dp[i]=min(dp[i],dp[i-j]);
            if(p[i])
                dp[i]+=1;
        }
        for(int i=l;i<=l+t;i++)
            dp[l]=min(dp[l],dp[i]);
        printf("%d\n",dp[l]);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章