Noip05过河题解

  • 题目描述 Description

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

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

  • 输入描述 Input Description

    输入第一行有一个正整数L(1≤L≤109),表示独木桥的长度。第二行有三个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离,及桥上石子的个数,其中1≤S≤T≤10,1≤M≤100。第三行有M个不同的正整数分别表示这M个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

  • 输出描述 Output Description

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

  • 样例输入 Sample Input

    10

    2 3 5

    2 3 5 6 7

  • 样例输出 Sample Output

    2

  • 数据规模

    对于30%的数据,L≤10000;

    对于全部的数据,L≤109。

  • 题解

    如果S == T,只需考察石子的位置是否是S的倍数。若是,则ans++。

    如果S != T,对于30%的数据,直接动规就可以。

    f[x]=min{f[x?i]}+stone[x]

    其中(S≤i≤T)∧(i≤x≤L+T),stone[x]=x处有石子?1:0

    但对于100%的数据,L的值显然太大。仔细观察,发现石子的个数很少,109的区间里只有不到100个。所以很自然地想到离散化压缩状态。

    先求M=max{lcm(x,y)},(x,y∈[S,T])

    对石子k,k+1,如果(*):dist[k]+n?M<dist[k+1](n为整数),可以把dist[k+1]缩短为dist[k]+(dist[k+1]?dist[k])modM。因为若(*)式成立,则n*M这段没有石子的距离可以由[S,T]内的数组合出来。所以这种放缩并不影响正确答案。把L一起放缩,只需令dist[M+1]=L,处理完dist数组后再令L=dist[M+1]即可。

    最后ans=min{f[i]}(i=放缩后的L→放缩后的L+T?1)

  • Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 10000000, M = 90;
int f[maxn];
bool d[maxn];
int l, a[102], s, t, m;
void init()
{
    scanf("%d", &l);
    scanf("%d%d%d", &s, &t, &m);
    for(int i = 0; i < m; ++i) scanf("%d", &a[i]);
    if(s == t)
    {
        int ans = 0;
        for(int i = 0; i < m; ++i)
           ans += (a[i] % s == 0 ? 1 : 0);
        printf("%d\n", ans);
        return;
    }
    a[m] = l; sort(a, a + m);
    for(int i = 0; i < m; ++i)
    {
        if(a[i + 1] - a[i] > M) a[i + 1] = a[i] + (a[i + 1] - a[i]) % M;
        d[a[i]] = true;
    }
    l = a[m];
}
void work()
{
    if(s == t) return;
    memset(f, 0x3F, sizeof(f)); f[0] = 0;
    for(int i = 1; i <= l + t; ++i)
    {
        for(int j = s; j <= t; ++j) if(i >= j)
            f[i] = min(f[i], f[i - j]);
        f[i] += d[i];
    }
    int ans = 0xFFFFFFF;
    for(int i = l; i < l + t; ++i) ans = min(ans, f[i]);
    printf("%d\n", ans);
}
int main()
{
    init();
    work();
    return 0;
}
时间: 2024-11-08 10:19:24

Noip05过河题解的相关文章

luoguP1502过河题解

日常吐(fei)嘈(hua) 这道题作为最近卡了我3天的dp题(最后还是在题解的帮助下冥思苦想才过掉的题),窝觉得此题肥肠之脑洞,写此博客纪念 题解 过河 先来日常手玩样例: 咦感觉怎么手玩答案都像是3的亚子??? 吓得我打开了讨论组 我们发现题目没说一定要踩到石子上,所以类似0->2->4->7->10的走法也是可以的 手玩样例成功√ 容易看出来这是个dp,因为走法无后效性. 那么我们思考dp式子.设\(dp[i]\)表示跳到距离原点\(i\)的地方,最少踩过的石子数.因为最终可

【基础练习】【线性DP+离散化】codevs1105 过河题解

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

P1052 过河 题解

复习dp(迪皮)的时候刷到了一道简单路径压缩的题目(一点不会qwq) 题目描述链接. 正解: 首先呢,我们看到题目,自然而然的会想到这种思路: 设状态变量dp[i]表示从第一个格子开始经过一些跳跃跳到第i个格子上所踩到的最小石子数目. 那么,根据每一次跳s~t个格子,我们可以得出dp[i]可以从dp[i-t]到dp[i-s]转移过来,要综合考虑的话呢,就要在所有之前的情况中取一个石子数最小的在加上当前位置是否有石子数,就是dp[i]的值. 于是呢,有了整体思路,我们开始敲起了代码. 浏览数组范围

[题解]RQNOJ PID87 过河

链接:http://www.rqnoj.cn/problem/87 思路:动态规划 定义f[i][j]表示到达第 i 块给定石头用了 j 块添加石头的最少步数. 转移方程:f[i][j]=min{f[k][j-tmp[pos[i]-pos[k]]+1]+tmp[pos[i]-pos[k]]} ,其中0<=k<i 且tmp[pos[i]-pos[k]]-1<=j 其中pos[i]表示第 i 块给定石头的坐标,tmp[i]表示跨过距离 i 需要添加的石头(相当于从坐标0出发到坐标 i ,注意

题解 P1052 【过河】

题目 在某人的挑唆之下来做了这道题,说是路径压缩dp,然鹅我做完以后并没有发现什么和路径压缩有关的东西. 题目的意思大概就是给你一条数轴和一些石子,再给你每一次可以往前走的长度区间,求想要走完这条数轴最少需要经过多少个石子. 首先对于30%的数据,\(L \leq 10000\),大概就是一个线性dp. 不难想到对于每一个点\(i\),都可以由\([i-s,i-t]\)转移过来. 设\(f[i]\)表示在点\(i\)时的最小答案,那么我们就有了一个最基本的转移方程:\(f[i]=min(f[k]

codevs1105 过河

1105 过河 2005年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度).坐标为0的点表示桥的起点,坐标为L的点表示桥的终点.青蛙从桥的起点开始,不停的

过河(bfs)

Problem 2188 过河I Accept: 112    Submit: 277 Time Limit: 3000 mSec    Memory Limit : 32768 KB  Problem Description 一天,小明需要把x只羊和y只狼运输到河对面.船可以容纳n只动物和小明.每次小明划船时,都必须至少有一只动物来陪他,不然他会感到厌倦,不安.不论是船上还是岸上,狼的数量如果超过羊,狼就会把羊吃掉.小明需要把所有动物送到对面,且没有羊被吃掉,最少需要多少次他才可以穿过这条河?

[codevs1105][COJ0183][NOIP2005]过河

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

1010 过河卒

1010 过河卒 2002年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点.例如上图 C 点上的马可以控制 9 个点(图中的P1,P2 … P8 和 C).卒不能通过对方马的控制点. 棋盘用坐标表示,A