• 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
  • 相关阅读:
    网络兼职轻松赚
    微信H5支付demo
    支付宝H5支付demo
    笔记本安装SSD固态硬盘详细的优化设置
    JQuery的AJAX
    第二次面试
    存储过程的总结
    SQl数据操作和查询
    面对考试毫无畏惧的SSH
    掷骰子-IOS新手项目练习(抱歉,由于个人原因,图片没显示,要源码的项目私聊)
  • 原文地址:https://www.cnblogs.com/mogeko/p/11649546.html
Copyright © 2020-2023  润新知