zoukankan      html  css  js  c++  java
  • BZOJ 1592: [Usaco2008 Feb]Making the Grade 路面修整( dp )

    最优的做法最后路面的高度一定是原来某一路面的高度.

    dp(x, t) = min{ dp(x - 1, k) } + | H[x] - h(t) | ( 1 <= k <= t ) 表示前 i 个路面单调不递减, 第 x 个路面修整为原来的第 t 高的高度. 时间复杂度O( n³ ).

    令g(x, t) = min{ dp(x, k) } (1 <= k <= t), 则转移O(1), g() 只需在dp过程中O(1)递推即可, 总时间复杂度为O( n² )

    然后单调不递增也跑一遍, 取最优 

    -----------------------------------------------------------------------------

    #include<bits/stdc++.h>
     
    #define rep(i, n) for(int i = 0; i < n; ++i)
    #define clr(x, c) memset(x, c, sizeof(x))
    #define foreach(i, x) for(__typeof(x.begin()) i = x.begin(); i != x.end(); i++)
     
    using namespace std;
     
    const int maxn = 2009;
    const int inf = 0x7fffffff;
     
    int H[maxn], h[maxn], dp[maxn][maxn], g[maxn][maxn], n;
     
    int main() {
    freopen("test.in", "r", stdin);
    cin >> n;
    rep(i, n) {
    scanf("%d", H + i);
    h[i] = H[i];
    }
    sort(h, h + n);
    rep(i, n) {
       dp[0][i] = abs(H[0] - h[i]);
       g[0][i] = i ? min(g[0][i - 1], dp[0][i]) : dp[0][i];
    }
    for(int i = 1; i < n; i++) 
       for(int j = 0; j < n; j++) {
        dp[i][j] = g[i - 1][j] + abs(H[i] - h[j]);
        g[i][j] = j ? min(g[i][j - 1], dp[i][j]) : dp[i][j];
       }
    int ans = g[n - 1][n - 1];
    for(int i = n - 1; ~i; i--) 
       g[0][i] = i != n - 1 ? min(g[0][i + 1], dp[0][i]) : dp[0][i];
    for(int i = 1; i < n; i++)
       for(int j = n - 1; ~j; j--) {
        dp[i][j] = g[i - 1][j] + abs(H[i] - h[j]);
        g[i][j] = j != n - 1 ? min(g[i][j + 1], dp[i][j]) : dp[i][j];
       }
    cout << min(ans, g[n - 1][0]) << " ";
    return 0;
    }

    ----------------------------------------------------------------------------- 

    1592: [Usaco2008 Feb]Making the Grade 路面修整

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 453  Solved: 333
    [Submit][Status][Discuss]

    Description

    FJ打算好好修一下农场中某条凹凸不平的土路。按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中。 整条路被分成了N段,N个整数A_1, ... , A_N (1 <= N <= 2,000)依次描述了每一段路的高度(0 <= A_i <= 1,000,000,000)。FJ希望找到一个恰好含N个元素的不上升或不下降序列B_1, ... , B_N,作为修过的路中每个路段的高度。由于将每一段路垫高或挖低一个单位的花费相同,修路的总支出可以表示为: |A_1 - B_1| + |A_2 - B_2| + ... + |A_N - B_N| 请你计算一下,FJ在这项工程上的最小支出是多少。FJ向你保证,这个支出不会超过2^31-1。

    Input

    * 第1行: 输入1个整数:N * 第2..N+1行: 第i+1行为1个整数:A_i

    Output

    * 第1行: 输出1个正整数,表示FJ把路修成高度不上升或高度不下降的最小花费

    Sample Input

    7
    1
    3
    2
    4
    5
    3
    9

    Sample Output

    3

    HINT

    FJ将第一个高度为3的路段的高度减少为2,将第二个高度为3的路段的高度增加到5,总花费为|2-3|+|5-3| = 3,并且各路段的高度为一个不下降序列 1,2,2,4,5,5,9。

    Source

  • 相关阅读:
    java与C#、.NET AES加密、解密 解决方案
    java 类名.class、object.getClass()和Class.forName()的区别 精析
    java instanceof和isInstance的关系 精析
    java 反汇编class文件
    织梦默认分页样式改动 解决分页列表显示,去掉li
    The method Inflate() in android
    leetcode第一刷_Edit Distance
    codeforces round #264(div2)
    android开发游记:SpringView 下拉刷新的高效解决方式,定制你自己风格的拖拽页面
    《linux 内核全然剖析》 chapter 4 80x86 保护模式极其编程
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4678841.html
Copyright © 2011-2022 走看看