【每日一题】5月9日 过河

过河

https://ac.nowcoder.com/acm/contest/253/B

题意:河宽L ,河中有m 个石子,青蛙想要过河,青蛙每次可以跳图片说明 的距离,问青蛙过河至少要踩多少块石子。
图片说明
分析:经典的状态压缩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]); 
}
每日一题 文章被收录于专栏

每日一题

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务