zoukankan      html  css  js  c++  java
  • 【luogu P2893】 [USACO08FEB]修路Making the Grade

    传送门:https://www.luogu.org/problemnew/show/P2893

    题目中的“原来的路的每一段海拔是A_i,修理后是B_i,花费|A_i – B_i|。我们要求修好的路是单调不升或者单调不降的。求最小花费。”第一眼看起来像上升子序列(显然不是),这是道线性dp的比较简单的题。首先一个合法的方案一定可以满足构造出的序列B使得∀x∈B 有x∈A,

    所以B序列一定是由多个x(x∈A)的连续段构成的,那么先将A离散化降低消耗,设f[i][j]为做完前i个数,最后一个数为j的最小花费,则有:

    f[i][j]=min(f[i−1][k]+∣A[i]−j∣)。

    时间复杂度为O(n^2),不会超时。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int maxn = 2005;
    int a[maxn], num[maxn], c[maxn];
    int f[maxn][maxn];
    int n;
    int main() {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            num[i] = a[i];
        }
        sort(num + 1,num + n + 1);
        int m = unique(num + 1,num + n + 1) - num - 1;
        for(int i = 1; i <= n; i++)
            c[i] = lower_bound
                   (num + 1,num + n + 1,a[i]) - num;
        memset(f,0x3f,sizeof(f));
        f[0][0] = 0;
        for(int i = 1; i <= n; i++) {
            int temp = f[i - 1][0];
            for(int j = 1; j <= m; j++) {
                temp = min(temp,f[i - 1][j]);
                f[i][j] = temp + abs(a[i] - num[j]);
            }
        }
        int ans = 1 << 30;
        for(int i = 1; i <= m; i++)
            ans = min(ans,f[n][i]);
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    C++友元
    C++类与static
    C++const
    reinterpret_cast应用
    学习软件工程课的心得上
    学习软件工程课的心得下
    项目总结报告之假如历史重新再来一次
    人月神话读后感
    团队任务考核
    冲刺周期会议十一
  • 原文地址:https://www.cnblogs.com/jiqimin/p/10992885.html
Copyright © 2011-2022 走看看