这一看是一个简简单单的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; }