链接: https://www.luogu.org/problemnew/show/P1052
AC代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int stone[109],f[350000],dis[109];
ll dp[350000];
int main() {
int len,maxn,minn,num;
cin>>len>>minn>>maxn>>num;
for(int i=1; i<=num; i++) {
cin>>stone[i];
}
sort(stone+1,stone+num+1);//输入工作
for(int i=1; i<=num; i++) {//2520是 1-10 的最小公倍数,所以两点相隔2520以上时,可以砍去一些距离
dis[i]=(stone[i]-stone[i-1])%2520;
}
for(int i=1; i<=num; i++) {
stone[i]=stone[i-1]+dis[i];//压缩路径后的石头相对位置
f[stone[i]]=1;//压缩路径之后的石头绝对位置
}
len=stone[num];//压缩路径之后的路径长度
fill(dp,dp+len+maxn+1,0x3f3f3f3f);
dp[0]=0;//起点没有石头,赋值为0
for(int i=1;i<=len+maxn;i++){//因为可能跳过终点,所以最后到达的是一个范围,而不是一个具体的点
for(int j=minn;j<=maxn;j++){
if(i>=j){
dp[i]=min(dp[i],dp[i-j]);
if(f[i]){
dp[i]+=1;//枚举每个可能走的步数,如果有石头就 +1
}
}
}
}
ll ans=0;
for(int i=len;i<len+maxn;i++){
ans=min(dp[i],dp[i+1]);//最后到达的是一个范围,这个范围内都算到达终点,所以选择一个踩到石头数量最少的
}
cout<<ans<<endl;
}