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

京公网安备 11010502036488号