码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu P1052 过河(dp)

时间:2018-11-04 15:37:33      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:描述   没有   过河   需要   text   org   int   code   clu   

P1052 过河

题意

题目描述

在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:\(0,1,\dots ,L\)(其中\(L\)是桥的长度)。坐标为\(0\)的点表示桥的起点,坐标为\(L\)的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是\(S\)\(T\)之间的任意正整数(包括\(S,T\))。当青蛙跳到或跳过坐标为\(L\)的点时,就算青蛙已经跳出了独木桥。

题目给出独木桥的长度\(L\),青蛙跳跃的距离范围\(S,T\),桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

输入输出格式

输入格式:

第一行有\(1\)个正整数\(L(1\leq L\leq 10^9)\),表示独木桥的长度。

第二行有\(3\)个正整数\(S,T,M\),分别表示青蛙一次跳跃的最小距离,最大距离及桥上石子的个数,其中\(1\leq S\leq T\leq 10,1 \le M \le 100\)

第三行有\(M\)个不同的正整数分别表示这\(M\)个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

输出格式:

一个整数,表示青蛙过河最少需要踩到的石子数。

输入输出样例

输入样例#1:

10
2 3 5
2 3 5 6 7

输出样例#1:

2

说明

对于\(30\%\)的数据,\(L\leq 10000\)

对于全部的数据,\(L\leq 10^9\)

\(2005\)提高组第二题

思路

先考虑部分分的做法。我们定义\(dp[i]\)为跳到坐标\(i\)时所需踩的最少石头数,那么\(dp[i]\)可以从\(dp[i-t],dp[i-t+1],\dots ,dp[i-s]\)转移过来。

但是当\(L\leq 10^9\)时,数组显然已经开不下了,就算空间够,时间上也不能完成。

想象这么一段区间,它以石头开头,以石头结尾,而且它十分的长,我们会发现,这一段区间中的大部分\(dp\)值相同,因为中间是没有石头踩的。所以我们可以把这么长的一段区间压缩成很少数目的点,然后直接\(dp\)就好了。

不过还有一个特例:当\(s=t\)时,不能用上述方法,我们就特判之后数学方法处理就好了。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=50005,B=100;
int l,s,t,m,last,ans=INT_MAX,dp[MAXN],a[105],p[MAXN],hjj[MAXN];
int read()
{
    int re=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
    return re;
}
int main()
{
    l=read(),s=read(),t=read(),m=read();
    for(int i=1;i<=m;i++) a[i]=read();
    if(s==t)
    {
        ans=0;
        for(int i=1;i<=m;i++) if(a[i]%s==0) ans++;
        printf("%d",ans);
        return 0;
    }
    a[0]=0,a[m+1]=l,m+=2;
    sort(a,a+m);
    for(int i=1;i<m;i++)
        if(a[i]-a[i-1]<=B) last+=a[i]-a[i-1],hjj[last]=1;
        else last+=B,hjj[last]=1;
    hjj[last]=0;
    memset(dp,0x3f,sizeof dp);
    dp[0]=0;
    for(int i=0;i<=last;i++)
        for(int j=s;j<=t;j++)
            dp[i+j]=min(dp[i+j],dp[i]+hjj[i+j]);
    for(int i=0;i<=t;i++) ans=min(ans,dp[last+i]);
    printf("%d",ans);
    return 0;
}

Luogu P1052 过河(dp)

标签:描述   没有   过河   需要   text   org   int   code   clu   

原文地址:https://www.cnblogs.com/coder-Uranus/p/9903912.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!