洛谷 P1052 过河 (压缩路径)

P1052 过河

题目描述

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

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

输入输出格式

输入格式:

 

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

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

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

 

输出格式:

 

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

 

输入输出样例

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

说明

对于30%的数据,L10000;

对于全部的数据,L10^9。

首先看到这道题目很容易想到跑dp的哇  然而定睛一看这个数据范围.....  1e9...

再见再见 是在下输了...

但是想来想去还是只有垃圾dp  然后又看到石头的数量是特别少的 所以很容易出现两个石头之间的路径特别特别长

所以就考虑压缩路径

想想怎么压缩呢 又可以看到每一步跳的范围也是很小的 在 $10$ 以内 所以考虑用 $lcm$ 压缩路径 并且使这段路径可以正常跑dp

怎么用 $lcm$ 压缩呢  如图 对于两块石头 $a,b$ 的一段路径 假定我们的压缩路径每段长度为 $2520$ ($1$ 到 $10$ 的$lcm$)

上面是压缩之后的 假设这一步距离为 $x$ 那么有他按照这个步伐不变 跳出压缩路径之后仍然落在这个点上

跳完这段路径要$k$ 步 则需要判断$2520 + x$ 与 $k * x$ 的关系

因为 $2520$ 是 $x$ 的倍数 所以 $x | 2520 + x$ 也就是说他会跳在同一个点 压缩路径成功

所以具体实现就是两块石头之间的路径长度模 $2520$ 剩下的长度正常跑 $dp$ 就可以了

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 3 * 1e6 + 5;
const int mod = 2520;
int n,L,S,T;
int dp[N],st[300],f[300];
bool vis[N];
int dis[105][105];

int main( ) {
    
    scanf("%d",& L);
    scanf("%d%d%d",& S,& T,& n);
    for(int i = 1;i <= n;i ++) {
        scanf("%d",& st[i]);
    }
    st[n + 1] = L;
    sort(st + 1,st + n + 2);
    int las = 0;
    f[0] = 0;
    memset(dp,0x3f3f3f,sizeof(dp));
    dp[0] = 0;
    for(int i = 1;i <= n + 1;i ++) { 
        f[i] = f[i - 1] + (st[i] - st[i - 1]) % mod;
        if(i != n + 1) vis[f[i]] = true;
    }
    for(int i = 1;i <= f[n + 1] + T;i ++) {
        for(int j = S;j <= T;j ++) {
            if(i - j < 0) break;
            if(vis[i]) dp[i] = min(dp[i],dp[i - j] + 1);
            else dp[i] = min(dp[i],dp[i - j]);
        }
    }
    int ans = 10000000;
    for(int i = f[n + 1];i <= f[n + 1] + T;i ++) 
        ans = min(ans,dp[i]);
    printf("%d",ans);
}

猜你喜欢

转载自www.cnblogs.com/Rubenisveryhandsome/p/9573923.html