dp+离散化
设dp[j]的含义是到位置j的陷进数,如果道路长度为1e9的话,数组是开不到这么大的,所以我们必须想办法缩短道路的长度,这就用到离散化了。
青蛙每次可以跳s-t之间的数,如果s==t的话,只需要枚举存储陷阱位置的数组,判断当前位置s是否可以走到即可。如果s!=t的话,我们来举个例子讨论下比如s=5 , t=6
跳一次 走到 5 - 6
跳两次 走到 10 - 12
跳三次 走到 15 - 18
跳四次 走到 20 - 24
跳五次 走到 25 - 30
跳六次 走到 30 - 36
跳七次 走到 35 - 42
跳八次 走到 40 - 48
跳九次 走到 45 - 54
跳十次 走到 50 - 60
我们可以发现在0 - st的位置中,并不是所有位置都可以走到,而在st以后的位置中都可以走到,既然这样,我们就可以把两点位置的距离>st的都变为st,这样的话,就缩短了道路的长度。举一个例子可能会理解的更明白一点
1e9
2 3 5
1 2 3 4 1e9
在这个例子里1e9>st,我们知道在大于st的位置,是一定可以走到的,我们与其去求到1e9的陷进数,倒不如去求到6的陷进数,因为他们两个的陷阱数是一样的,而且6又比1e9小,可以减少dp数组的空间。为什么说他们的陷阱数是一样呢?是因为他们之间没有其它陷阱,倒数第二个陷阱数在4这个位置,倒数第一个在1e9这个位置。但是如果数据是这样的 1 2 3 1e9 4 ,这样就不行了,因为在1e9 后面还有一个位于陷阱,这个陷阱的位置在1e9前面,如果我们还按照之前的方法算的话,计算到6的陷阱数,到6得以有到4和到3走到,但是我们还没有计算4这个位置的陷阱数,所以计算出来的结果是错误的(样例会卡这样的数据,所以我们直接对数组排序就可以了,这样就避免这样的情况发生)
到这里整体思路就讲完了,接下来说一下细节处理

//这是离散化的代码
  for(int i=1;i<=m;i++){
        int dis=arr[i]-arr[i-1];
        if(dis>s*t)dis=s*t;
        now[i]=now[i-1]+dis;
        vis[now[i]]=1;
    }

说一下now这个数组的作用,因为离散化处理之后,位置都会发生改变,我们要开一个数组,记录下离散化处理之后,每个元素的位置,now[m]对应的就是arr中最后一个元素离散化的位置,如果桥的长度大于最后一个陷阱的位置加st那么到桥终点的方案数就等于到now[m]+st的位置的方案数,所以桥的长度l=now[m]+s*t

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int arr[1110];
int vis[maxn];
int dp[maxn];
int now[110];
const int inf=0x3f3f3f3f;
int main(){
    int l;
    cin>>l;
    int s,t,m;
    cin>>s>>t>>m;
    for(int i=1;i<=m;i++){
        cin>>arr[i];
    }
    sort(arr+1,arr+1+m);
    if(s==t){
        int count=0;
        for(int i=1;i<=m;i++){
            if(arr[i]%s==0)count++;
        }
        cout<<count;
        return 0;
    }
    //now[0]=0;
    //memset(vis,0,sizeof(vis));
    for(int i=1;i<=m;i++){
        int dis=arr[i]-arr[i-1];
        if(dis>s*t)dis=s*t;
        now[i]=now[i-1]+dis;
        vis[now[i]]=1;
    }
    l=now[m]+s*t;
    memset(dp,inf,sizeof(dp));
    dp[0]=0;
    for(int i=1;i<=l;i++){
        for(int j=s;j<=t;j++){
            if(i>=j)
            dp[i]=min(dp[i],dp[i-j]+vis[i]);
        }
    }
    int ans=inf;
    for(int i=now[m];i<=l;i++){
        ans=min(ans,dp[i]);
    }
    cout<<ans;
    return 0;
}