zoukankan      html  css  js  c++  java
  • Luogu P1052 过河

    gate

    设跳到i最少踩到的石子数为f[i],j ∈ (s,t),

    c[i]为i是否有石子。

    dp方程:f[i] = min(f[i-j]+c[i])

    看起来很简单的样子?

    但是这道题的数据范围比较奇怪,桥的距离有1e9,显然数组开不下…

    不过石子的个数只有100,而且跳的距离只有1~10。

    所以两个石子中间可能有很大一段距离没有东西,可以利用这个性质把石子的距离离散化一下。

    设相邻两个石子的距离为d。

    如果d>t,可以知道,f[i]一定可以由f[i-t]转移过来。

    也就是说,当相邻两个石子之间的距离为(d%t)+t+t+...+t时,多出来的t不会对答案造成影响。

    那么,可以将距离超过t的相邻石子的距离都改为d%t+t(加t是因为还是一定要跳到中间的一个点)。

    因为最后一个可能对答案产生影响的点就是最后一个石子的位置(设为b[m]),

    并且只要跳过终点,不一定刚好在终点,

    所以答案枚举(b[m],b[m]+t)就可以了。

    注意:初始化f[0] = 0

    代码如下

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #define MogeKo qwq
    #include<algorithm>
    using namespace std;
    
    const int maxn = 20005;
    const int INF = 105;
    int l,s,t,m,ans;
    int a[maxn],b[maxn],c[maxn],f[maxn];
    
    int main() {
        scanf("%d",&l);
        scanf("%d%d%d",&s,&t,&m);
        for(int i = 1; i <= m; i++)
            scanf("%d",&a[i]);
        sort(a+1,a+m+1);
        for(int i = 1; i <= m; i++) {
            int d = a[i]-a[i-1];
            if(d <= t)    
                b[i] = b[i-1] + d;
            else
                b[i] = b[i-1] + d%t+t;
        }
        for(int i = 1; i <= m; i++)
            c[b[i]] = 1;
        
        ans = INF;
        for(int i = 1;i <= b[m]+t;i++)
            f[i] = INF;
        for(int i = s; i <= b[m]+t; i++)
            for(int j = s; j <= t; j++)
                f[i] = min(f[i],f[i-j]+c[i]);
        for(int i = b[m]; i <= b[m]+t; i++)
            ans = min(ans,f[i]);
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    hihocoder #1388 : Periodic Signal NTT&FFT
    HDU 5895 Mathematician QSC(矩阵乘法+循环节降幂+除法取模小技巧+快速幂)
    hdu 5894 hannnnah_j’s Biological Test 组合数学
    csu 1812: 三角形和矩形 凸包
    地铁 Dijkstra(优先队列优化) 湖南省第12届省赛
    后缀自动机专题
    数学渣的自我修养!!!
    高斯消元(浮点)
    The PLAN
    ccpc网络赛
  • 原文地址:https://www.cnblogs.com/mogeko/p/11649546.html
Copyright © 2011-2022 走看看