zoukankan      html  css  js  c++  java
  • 【洛谷】P1052 过河【DP+路径压缩】

    P1052 过河

    题目描述

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

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

    输入输出格式

    输入格式:

    第一行有1个正整数L(1L109),表示独木桥的长度。

    第二行有3个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离及桥上石子的个数,其中1ST10,1M100。

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    10
    2 3 5
    2 3 5 6 7
    
    输出样例#1: 复制
    2

    说明

    对于30%的数据,L10000;

    对于全部的数据,L109。

    2005提高组第二题

    一开始被题目坑惨了啊...看到题就打了个建边$Spfa$,然后样例怎么过不了???

    仔细研读样例发现是在可以不踩石头的情况下最少要踩几个石头啊!!!

    然后重新定义dp方程...发现$S$和$T$是小于等于10的,$L$又莽大。所以考虑如何把空间压下去。考虑路径压缩。

    以下贴的洛谷大佬Panda_hu的题解:

    当然,我觉得还是直接$mod$2520比较好理解...因为在10范围内,不论怎么跳,都可以跳到2520,所以只要两个石头距离大于2520的时候,直接$mod$2520。

    路径压缩了过后扫一遍更新即可,如果当前有石头就必须踩。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    int L, S, T, M, f[3000005], flag[3000005], d[105];
    
    struct Node {
        int pos;
    } Stone[105];
    bool cmp ( Node a, Node b ) { return a.pos < b.pos; }
    
    int main ( ) {
        scanf ( "%d", &L );
        scanf ( "%d%d%d", &S, &T, &M );
        for ( int i = 1; i <= M; i ++ )
            scanf ( "%d", &Stone[i].pos );
        sort ( Stone + 1, Stone + 1 + M, cmp );
        for ( int i = 1; i <= M; i ++ )
            d[i] = ( Stone[i].pos - Stone[i-1].pos ) % 2520;
        for ( int i = 1; i <= M; i ++ ) {
            Stone[i].pos = Stone[i-1].pos + d[i];
            flag[Stone[i].pos] = 1;
        }
        memset ( f, 0x3f3f3f3f, sizeof ( f ) );
        f[0] = 0;
        for ( int i = 1; i <= Stone[M].pos + T; i ++ ) {
            for ( int j = S; j <= T; j ++ )
                if ( i - j >= 0 ) f[i] = min ( f[i-j], f[i] );
            f[i] += flag[i];
        }
        int ans = 0x3f3f3f3f;
        for ( int i = Stone[M].pos; i < Stone[M].pos + T; i ++ )
            ans = min ( ans, f[i] );
        printf ( "%d", ans );
        return 0;
    }
  • 相关阅读:
    周末单车行
    大笨
    随谈个人所得税起征点
    我的新球拍
    谈“家乐福抵制门”事件
    49届世乒赛(团体)电视转播时间表
    上海动物园拍摄记
    一个老外的故事
    请大家帮忙推荐一款名片管理软件
    不要先挂电话
  • 原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/9570531.html
Copyright © 2011-2022 走看看