USACO Making the Grade

洛谷 P2893 [USACO08FEB]修路Making the Grade

https://www.luogu.org/problemnew/show/P2893

JDOJ 2566: USACO 2008 Feb Gold 1.Making the Grade

https://neooj.com:8082/oldoj/problem.php?id=2566

POJ Making the Grade

http://poj.org/problem?id=3666

Description

A straight dirt road connects two fields on FJ's farm, but it changes
elevation more than FJ would like. His cows do not mind climbing
up or down a single slope, but they are not fond of an alternating
succession of hills and valleys. FJ would like to add and remove
dirt from the road so that it becomes one monotonic slope (either
sloping up or down).

You are given N integers A_1, . . . , A_N (1 <= N <= 2,000) describing
the elevation (0 <= A_i <= 1,000,000,000) at each of N equally-spaced
positions along the road, starting at the first field and ending
at the other. FJ would like to adjust these elevations to a new
sequence B_1, . . . , B_N that is either nonincreasing or nondecreasing.
Since it costs the same amount of money to add or remove dirt at
any position along the road, the total cost of modifying the road
is

          |A_1 - B_1| + |A_2 - B_2| + ... + |A_N - B_N|

Please compute the minimum cost of grading his road so it becomes
a continuous slope. FJ happily informs you that signed 32-bit
integers can certainly be used to compute the answer.

Input

* Line 1: A single integer: N

* Lines 2..N+1: Line i+1 contains a single integer elevation: A_i

Output

* Line 1: A single integer that is the minimum cost for FJ to grade
        his dirt road so it becomes nonincreasing or nondecreasing in
        elevation.

Sample Input

7 1 3 2 4 5 3 9

Sample Output

3

HINT

 

OUTPUT DETAILS:

By changing the first 3 to 2 and the second 3 to 5 for a total cost of
|2-3|+|5-3| = 3 we get the nondecreasing sequence 1,2,2,4,5,5,9.

 
题目大意:
给定长度为N的序列A,构造一个长度为N 的序列B。
要求B非严格单调,并最小化花费(Ai-Bi的绝对值)
 
题意分析:
马上想到动归。
思路不是特别好想,状态转移方程也不是特别好设。
首先我们需要明确,在满足花费最小化的前提下,一定存在一种构造B的方案,使得B中的每个数都是A序列中的。
可以证明:
假设结论针对于N=K-1成立,那么对于数列N=K,在满足单调性的情况下,可以令Bk=Ak,命题仍成立。
否则的话,令Bk=Bk-1,命题也成立,也就是说可以层层递推下去,一直到N=1的情况。
而显然N=1的情况下命题是成立的。
证毕,命题成立。
我们只是证明这种情况(B中所有元素都是A的一部分)存不存在,并不是在证明只要存在就一定是这种情况。
所以才有了上面的证明过程,证明出这种情况可以存在,为之后的解题过程提供了思路基础。
回到本题。
这道题是构造类型的动态规划。我的思路是,设F[I][J]为完成前i个数的构造,其中Bi=j时,S的最小值。
根据刚刚证明的命题,我们可以考虑把A的数据离散化之后存到B中,离散化的功用是降低时间复杂度,这样一个O(N3)的算法就会被我们降成O(N2)。
这样就比较完美了,通过动归求出非严格单调递减之后,仿照这个思路再求一遍非严格单调递增,答案可求。
 
AC CODE:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,ans,a[2001],t[2001],b[2001];
int f[2001][2001],minf[2001][2001];
bool cmp(int a,int b)
{
    return a>b;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        t[i]=a[i];
    }
    sort(t+1,t+n+1);
    int now=-1;
    for(int i=1;i<=n;i++)
        if(now!=t[i])
            b[++m]=t[i],now=t[i];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            f[i][j]=minf[i-1][j]+abs(a[i]-b[j]);
            if(j==1)
                minf[i][j]=f[i][j];
            else
                minf[i][j]=min(minf[i][j-1],f[i][j]);
        }
    ans=minf[n][m];
    memset(f,0,sizeof(f));
    memset(minf,0,sizeof(minf));
    sort(b+1,b+m+1,cmp);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            f[i][j]=minf[i-1][j]+abs(a[i]-b[j]);
            if(j==1)
                minf[i][j]=f[i][j];
            else
                minf[i][j]=min(minf[i][j-1],f[i][j]);
        }
    ans=min(ans,minf[n][m]);
    printf("%d",ans);
    return 0;
}

 

posted @ 2019-07-17 10:52  Seaway-Fu  阅读(213)  评论(0编辑  收藏  举报