题意:河宽 ,河中有
 个石子,青蛙想要过河,青蛙每次可以跳
 的距离,问青蛙过河至少要踩多少块石子。
分析:经典的状态压缩dp.
- 我们先不考虑范围,先将所有石子的位置进行排序,到第 的位置最少踩的石子数量.转移方程: 
- 显然空间太大,那么考虑如何优化空间.
 其实很多是没有意义的,假如 远大于 ,那么对于下标为 到下标为 的dp值 有很多部分并无实际转移价值。考虑压缩dp状态. 
- 每次青蛙跳跃的距离是,那么 以后的距离是都能到达的,如果两个石子间的距离大于 的话,我们将状态压缩为 .那么空间就优化完成了. 
- 那么如何得到最终答案.
 我们并不知道终点在哪里,但是我们知道起点的位置。那么我们考虑从逆向dp求解得到答案。 
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int len,s,t,m,ans;
int a[maxn],b[maxn],dp[maxn];
int main()
{
    cin>>len>>s>>t>>m;
    for( int i=1;i<=m;i++ ) cin>>a[i];
    if( s==t )
    {
        for( int i=1;i<=m;i++ ) 
        {
            if( a[i]%s==0 ) ans++; 
        }
        printf("%d\n",ans);
        return 0;
    }
    sort(a+1,a+1+m);
    int ed=0,base=s*t;
    for( int i=1;i<=m;i++ )
    {
        if( a[i]-a[i-1]>=base ) ed+=base;
        else ed=ed+a[i]-a[i-1];
        b[ed]=1;
    }
    for( int i=ed;i>=0;i-- )
    {
        dp[i]=100;
        for( int j=s;j<=t;j++ ) dp[i]=min(dp[i],dp[i+j]+b[i]);
    }
    printf("%d\n",dp[0]); 
}
 京公网安备 11010502036488号
京公网安备 11010502036488号