zoukankan      html  css  js  c++  java
  • noip2005提高组 过河

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

    已知信息:
    独木桥的长度,青蛙一次最多能够跳过的距离x∈[S, T], 石子的数量及每个石子的位置

    求青蛙最少要跳过多少石子

    因为点的坐标可能很大,所以不能用下标来表示石子,首先要对坐标进行离散。
    由题目可以知道一个很重要的信息:
    青蛙不是一定要跳到石头上!!!而是说青蛙跳完整段独木桥,要求踩到的石子尽可能的少,就是说在青蛙跳过独木桥时,可能会有不得不踩到的石子,我们要求这个数量尽可能的少
    这样我们首先可以设:
    f[i]表示在点i时跳过的最小的石头的数量,这样为了跳到i点,青蛙就必须在[i - s, i - t]区间内的点起跳,所以我们要在这个区间内取最小的更新当前位置
    为了方便起见,我们将这个区间内有石头的点用flag数组标为1,这样就有
    f[i] = min{f[i - j] + flag[i]}(i - s <= j <= i - t)
    但是10^9的点告诉我们,我们显然不能随便去搜,而且,我们数组也不能随便开。
    但是我们能够注意到,所有的操作,其实只和[s, t]有关,我们实际用到的区间长度只有[s, t]这一段
    我们想,当两点的距离d大于t时,我们发现实际上中间有k段长达t的距离是不必要的,这些距离对于我们的青蛙是否会跳到石头上是没有影响的,这样我们可以把这k段距离通过%t来%掉。
    这样也就是说对于两个点x1, x2,之间的距离为d,我们假设由x1跳到x2,实际等价于x1跳d%t的距离到x2
    根据这个思路,我们想我们可以先计算出我们这样搞最后所需要的总共的距离的和
    但是要注意的是,对于两个点x1, x2,这之间的距离为d%t,但是总距离时我们还需要在单独加上t,因为剩下的d%t,我们知道这个距离是肯定小于t的,这样可能导致我们一些情况的缺失(意会一下就好)
    这样我们最后总的最多需要的长度近似等于2 * t *m,最后也就是说我们把10^9的长度近似压缩成了2 * t * m
    这样我们就可以很愉快的DP了
    需要注意的是,我们并不一定会一定跳在桥的重点,而是只要跳过桥就好,所以最后我们的答案要在一个范围内取min值

    //当然,我做不到大佬们那么严谨的证明,建议不要看我的题解

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int maxn = 21000;
     5 int l, s, t, m;
     6 int a[maxn], f[maxn];
     7 int vis[maxn];
     8 int len = 0;
     9 
    10 inline int read() {
    11     int x = 0, y = 1;
    12     char ch = getchar();
    13     while(!isdigit(ch)) {
    14         if(ch == '-') y = -1;
    15         ch = getchar();
    16     }
    17     while(isdigit(ch)) {
    18         x = (x << 1) + (x << 3) + ch - '0';
    19         ch = getchar();
    20     }
    21     return x * y;
    22 }
    23 
    24 int main() {
    25     memset(f, 0x3f3f, sizeof(f));
    26     memset(vis, 0, sizeof(vis));
    27     l = read();
    28     s = read(), t = read(), m = read();
    29     for(int i = 1; i <= m; ++i)
    30         a[i] = read();
    31     a[m + 1] = l;
    32     sort(a + 1, a + m + 2);
    33     for(int i = 1; i <= m + 1; ++i) {
    34         if(a[i] - a[i - 1] >= t)
    35             len += (a[i] - a[i - 1]) % t + t;
    36         else len += a[i] - a[i - 1];
    37         vis[len] = 1;
    38     }
    39     vis[len] = 0;
    40     f[0] = 0;
    41     for(int i = s; i <= len + t - 1; ++i)
    42         for(int j = s; j <= t; ++j)    
    43             f[i] = min(f[i], f[i - j] + vis[i]);
    44     int ans = 0x3f3f3f;
    45     for(int i = len; i <= len + t - 1; ++i)
    46         ans = min(ans, f[i]);
    47     cout << ans << '
    ';
    48     return 0;
    49 }
    View Code
  • 相关阅读:
    Web.config Transformation Syntax for Web Application Project Deployment
    xcode 8.1 (8B62)真机调试配置
    主机与虚拟机互ping
    mac系统下安装mysql步骤
    iphone设备尺寸规格
    linux环境下oracle静默安装
    实现静默安装APK的方法
    mac系统下如何删除银行安全插件
    mac系统下设置eclipse的补全快捷键方法
    给Xcode增加复制行、删除行快捷键的方法
  • 原文地址:https://www.cnblogs.com/ywjblog/p/9262865.html
Copyright © 2011-2022 走看看