zoukankan      html  css  js  c++  java
  • 【33.00%】【vijos P1002】过河

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

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

    输出只包括一个整数,表示青蛙过河最少需要踩到的石子数。
    样例1
    样例输入1[复制]

    10
    2 3 5
    2 3 5 6 7
    样例输出1[复制]

    2
    限制
    1s
    来源
    NOIp2005 第二题

    【题解】

    很容易想到方程
    f[i] =min(f[i-t..i-s]) + 1;(i处有石头)
    f[i] =min(f[i-t..i-s]);(i处没有石头)
    但是n很大。不能直接写;
    需要优化;
    ->m很小只有100;
    则如果n到了极限数据1e9;
    那么相邻的石头之间,或者石头和起点和终点直接的距离可能会非常大。
    则可以在这里做文章->每次走一大段没石头的长度;
    这个长度应该是多少呢?
    有这样一个方程
    x*p+y*(p+1) = Q
    当Q大于等于p*(p-1)的时候;
    该方程恒有解;
    例如
    4 5
    则 12,13,14…都可以通过这两种步数得到
    即12之后连续的数字都能通过4和5累加得到;
    找到了证明:

        •由于p与p+1间隔1,故方程px+(p+1)y=Q有整数解,设其解为
        • x=x0+(p+1)t,y=y0-pt(t是整数)
        •取适当的t,使得0≤x≤p(只需在x0上加上或减去若干个p+1),则当Q>p(p-1)-1时,有
        •(p+1)y=Q-px>p(p-1)-1-px≥p(p-1)-1-p*p=-(p+1)
        •于是y>-1,故y≥0也是非负整数。证毕.


    则如果我们发现两个相邻的石头之间的距离大于s*(s-1)+t则直接让其变成s*(s-1)+t就好.
    例子:
    石头x 1 2 3…1000 1001 1002 石头y
    石头y之后的状态往前找前一个状态的时候最多就是1002-t;
    不会在往前了;
    则如果s*(s-1) +t< 1002
    则从s*(s-1)开始的数字都能连续取到了;然后再加上t用来替代原来石头y之后的状态的转移;
    这样就变成
    石头x 1 2 3.. s*(s-1)+t-t,s*(s-1)+t-(t-1)…s*(s-1)+t 石头y;
    石头y以及后面的状态都能够从
    s*(s-1)+t-t,s*(s-1)+t-(t-1)…s*(s-1)+t这一段得到转移;
    所以不会影响原来的解;
    多想想吧。
    再换个思路理解下:
    这里写图片描述
    从石头x左边t处的石头转移到x处,之后,因为石头x和y之间没有任何石头了。所以这个状态不会变化。而经过s*(s-1)之后就能够把状态传递到y-t了。上面那个方程保证了我们一定能够把x的状态通过有限次的s和s+1这两种步数传递到s*(s-1)(因为我们把这个x和y之间的距离变成了s*(s-1)+t)
    然后同理
    x+1-t的状态会传递到x+1的位置。然后经过s*(s-1)也能传递到s*(s-1)+1.则y后面的状态也能通过减t得到这个状态。
    依次类推。。
    重要的在于这些状态在这两个石头之间不会再发生变化了。只是单纯地传递.

    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    const int MAXM = 150;
    const int INF = 2100000;
    
    int l, s, t, m;
    int pos[MAXM];
    int f[10000];
    int should[MAXM];
    
    int main()
    {
        //freopen("F:\rush.txt", "r", stdin);
        scanf("%d", &l);
        scanf("%d%d%d", &s, &t, &m);
        for (int i = 1; i <= m; i++)
            scanf("%d", &pos[i]);
        sort(pos + 1, pos + 1 + m);
        if (s == t)
        {
            int ans = 0;
            for (int i = 1; i <= m; i++)
                if (!(pos[i] % s))
                    ans++;
            printf("%d
    ", ans);
        }
        else
        {
            int MOD = s*(s - 1) + t;
            for (int i = 1; i <= m; i++)
            {
                should[i] = pos[i] - pos[i - 1];
                if (should[i] > MOD)
                    should[i] = MOD;
            }
            int temp1 = l - pos[m];
            if (temp1 > MOD)
                temp1 = MOD;
            for (int i = 1; i <= m; i++)
                pos[i] = pos[i - 1] + should[i];
            int maxl = pos[m] + temp1;
            for (int i = 1; i <= m; i++)
                f[pos[i]] = 1;
            for (int i = 1; i <= maxl; i++)
            {
                int mi = INF;
                for (int j = s; j <= t; j++)
                    if (i - j >= 0)
                        mi = min(mi, f[i - j]);
                f[i] += mi;
            }
            int ans = f[maxl];
            for (int i = maxl + 1; i <= maxl + t; i++)
            {
                int mi = INF;
                for (int j = s; j <= t; j++)
                    if ((i - j >= 0) && (i - j) < maxl)
                        mi = min(mi, f[i - j]);
                if (ans > mi)
                    ans = mi;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    BZOJ2870 最长道路
    BZOJ1316 树上的询问
    BZOJ2238 Mst
    BZOJ4242 水壶
    [BeiJing2010组队]次小生成树Tree
    CODEVS1403 新三国争霸
    牛客网NOIP赛前集训营-提高组(第六场) C-树
    JSOI2008 最小生成树计数
    BZOJ2654 Tree
    牛客网NOIP赛前集训营-提高组(第六场)B-选择题
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632132.html
Copyright © 2011-2022 走看看