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

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把路修成高度不上升或高度不下降的最小花费

题解:

以不下降序列为例,定义F[i][j]为第i个数调整为高度等于或小于j时的最小支出。

于是有F[i][j]=min{F[i-1][j]+abs(h[i]-j),F[i][j-1]}.

需要离散化。

ans=F[n][MAX]

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
//by zrt
//problem:
using namespace std;
int c[2005];
int a[2005];
int cc;
int n;
int f[2005][2005];
bool cmp(int a,int b){
    return a>b;
}
int main(){
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        c[i]=a[i];
    }
    sort(c+1,c+n+1);
    cc=unique(c+1,c+n+1)-(c+1);
    for(int i=1;i<=n;i++) f[i][0]=1<<30;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=cc;j++){
            f[i][j]=f[i-1][j]+abs(a[i]-c[j]);
            f[i][j]=min(f[i][j],f[i][j-1]);
        }
    }
    int ans=f[n][cc];
    sort(c+1,c+cc+1,cmp);
    for(int i=1;i<=n;i++) f[i][0]=1<<30;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=cc;j++){
            f[i][j]=f[i-1][j]+abs(a[i]-c[j]);
            f[i][j]=min(f[i][j],f[i][j-1]);
        }
    }
    ans=min(f[n][cc],ans);
    printf("%d\n",ans);
    return 0;
}
时间: 2024-10-22 13:51:28

BZOJ 1592: [Usaco2008 Feb]Making the Grade 路面修整的相关文章

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² ) 然后单调不递增也跑一遍

[BZOJ1592][Usaco2008 Feb]Making the Grade 路面修整

1592: [Usaco2008 Feb]Making the Grade 路面修整 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 735  Solved: 509 [Submit][Status][Discuss] Description FJ打算好好修一下农场中某条凹凸不平的土路.按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中. 整条路被分成了N段,N个整数A_1, ...

【BZOJ 1592】[Usaco2008 Feb]Making the Grade 路面修整 dp优化之转移变状态

我们感性可证离散(不离散没法做),于是我们就有了状态转移的思路(我们只考虑单不减另一个同理),f[i][j]到了第i块高度为j的最小话费,于是我们就可以发现f[i][j]=Min(f[i-1][k])+|a[i]-j|(k<=j),于是我们的思路就去了各种数据结构--.然后我们发现对于这些转移就是在记录小于等于,那么我们直接带状态里体现这一点就可以了,而不是在转移的时候,我们f[i][j]表示到了第i个点小于等于j的高度的最小花费,这样我们就n^2了. #include <cstdio>

BZOJ 1592 Usaco 2008 Feb Making the Grade 路面修整 DP

题目大意:给出一个不整齐的路面,可以将一个路面升高或者降低,都需要话费|x - x'|的费用,把路面修正成单调不降或单调不升的最小花费是多少. 思路:路面的高度跨度有点大啊,先离散化.之后f[i][j] 表示到i为止路面保证单调不降并且最高高度为j的最小花费是多少,利用一个前缀和优化一下.单调不升也一样,简单DP水过.. CODE: #include <map> #include <cstdio> #include <cstring> #include <iost

bzoj 1593: [Usaco2008 Feb]Hotel 旅馆

1593: [Usaco2008 Feb]Hotel 旅馆 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 800  Solved: 441[Submit][Status][Discuss] Description 奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光.作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿.这个巨大的旅馆一共有N (1 <= N <= 50,000)间客房,它们在同一层楼中顺次一字排

BZOJ 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐( LIS )

求LIS , 然后用 n 减去即为answer ---------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define rep( i , n ) for( int i = 0 ;  i < n ; ++i )

【bzoj1592/Usaco2008 Feb】Making the Grade 路面修整——dp

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,作为修过的路中每个路段的高度.由于将每一段路垫高

BZOJ 1609: [Usaco2008 Feb]Eating Together

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1609 解:题目很明显,我们只要找到最长不下降子序列,然后总长度减去它的长度就可以了,用o(nlogn)的方法. 但是,用O(9n)的动归,显然更优(吧...) 我学习了一下他人的动归. 用f[i][j](1<=i<=n;j=1,2,3)来表示序列前i个的时候,我们当前用j 这个数字结尾最多需要改几个.当然我们还要枚举上一段的位置,具体我程序里写吧. #include<iostre

BZOJ 1611: [Usaco2008 Feb]Meteor Shower流星雨

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1611 解:直接广搜... 程序: #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> #define maxn 210000000 using namespace std; int ans; int f[500][5