解题思路:这题的状态转移方程还是很好想的,dp[i]代表跳到第i点踩到的最少石头,dp[i]=dp[i-j]+stone[i],j位距离,即跳j个距离到i点,stone[i]表示这里是否有石子。但是这里l非常大,只是循环也会超时,所以需要状态压缩。这里压缩的方法有90缩,72缩(戳我)还有2520缩,这里我写的是2520缩,这个很好理解,2520是1~10的最小公倍数,就是从i点出发,每个点都可以到达距离+2520处,之后又会出现重复的情况,所以只要对2520取余就行了,最大也就是2520*100。
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=1e6+5;
const int mod=2520;
int dp[maxn];
int stone[maxn],a[maxn];
int l,s,t,m;
int main(){
std::ios::sync_with_stdio(0);
cin>>l>>s>>t>>m;
for(int i=1;i<=m;++i){
cin>>a[i];
}
sort(a+1,a+m+1);
int k=0;
for(int i=1;i<=m;++i){
if(a[i]-a[i-1]>mod){ //距离大了
k+=(a[i]-a[i-1])-(a[i]-a[i-1])%mod;
}
stone[a[i]-k]=1;
}
memset(dp,0x3f,sizeof(dp));
dp[0]=0;
for(int i=1;i<=mod*m;++i){
for(int j=t;j>=s;--j){
if(i-j>=0){
dp[i]=min(dp[i-j]+stone[i],dp[i]);
}
}
}
cout<<dp[mod*m]<<endl;
return 0;
}