这一看是一个简简单单的dp 转移方程一下子就推出来了
但是一写就发现 范围怎么这么大(憨批如我还真开了一次1e9的数组)
这题击中了我的盲区 but 我的巨佬队友说这题太基础了(在洛谷有三万多提交
这题主要是离散化(名词真熟悉 不会
在翻阅了十几篇题解过后 我终于明白了
离散化就是在一个大范围内 目标点之间的距离够大导致怎么走都满足题目要求 于是就将大间隔改成小间隔 于是数据范围就缩小了 可以用数组操作了
在这题我们可以证明 当两个石子范围超过st时 任意距离都可以到达 于是间隔就可以改成st (s<t s==t特判一下就行了
代码有详细注释

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
int const N=150;
int const M=300*105;
int const INF=1e9+7;
int l,s,t,m,a[N],b[N],dp[M],maxn;
bool vis[M];
int main()
{
    cin>>l>>s>>t>>m;
    maxn=s*t;
    for(int i=1;i<=m;++i)cin>>a[i];
    sort(a+1,a+1+m);
    if(s==t){///特判s==t
        int cnt=0;
        for(int i=1;i<=m;++i)if(a[i]%s==0)cnt++;
        cout<<cnt<<endl;
        return 0;
    }
    for(int i=1;i<=m;++i){///如果石子距离大于s*t  就缩小成s*t
        int dis=a[i]-a[i-1];
        if(dis>=maxn)dis=maxn;
        b[i]=b[i-1]+dis;
        vis[b[i]]=1;
    }
    l=b[m]+maxn;
///  将l变成最后一个石头的位置+s*t
///  如果l-b[m]>=s*t就缩成s*t
///  如果l-b[m]<=s*t就加上一个数使得它等于这个距离因为青蛙可能跳出独木桥
    memset(dp,0x7f,sizeof(dp));///dp初始化为大值
    dp[0] = 0;/// 初始化到原点寻最少踩0个石头
    for(int i=1;i<=l;++i){
        for(int j=s;j<=t;++j){
            if(i-j>=0){
                if(vis[i]) dp[i]=min(dp[i-j]+1,dp[i]);
                else dp[i]=min(dp[i-j],dp[i]);
            }
        }
    }
    int ans=INF;
    for(int i=b[m];i<=l;++i)ans = min(ans,dp[i]);///从桥尾开始 因为有可能跳出去
    cout<<ans<<endl;
    return 0;
}