Making the Grade POJ - 3666(離散化+dp)

zeng_jun_yv發表於2020-09-26

題意:

給你n個山的高度,單獨的一個數可以任意加減,讓經過對每座山峰任意加減高度後變成遞增或遞減的序列時,求對每個數的相加或相減的數目的最小和。

題目:

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 A1, … , AN (1 ≤ N ≤ 2,000) describing the elevation (0 ≤ Ai ≤ 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 B1, . … , BN 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

|A1 - B1| + |A2 - B2| + … + |AN - BN |
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: Ai

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

分析:

前言:這道題糾結了好久,原因是我沒想到離散化,知道用離散化後,我還是轉不過來,認為經過增加或減少後,山峰的高度不為原始高度的任意一種,所以認為離散化不是最優的,其實到現在我還是這麼認為,但由於山峰高度過高,哪怕離散化過後列舉複雜度還是有o( n 2 n^{2} n2),所以我妥協了(在這裡求助,如果有大犇有關於這道題離散化更好地理解,希望能給我一些幫助,嘻嘻)
1.這道題dp還是好理解的,即離散化過後每次列舉當第i個山峰到達某山峰高度,dp[i][j]表示把前i個數變成單調增且第i個數變成原來第j大的數的最小代價。
2、把給定的山峰高度排好序,就成為其離散的遞增或遞減的高度。
3、對第一點進行與排好序的最小值的點進行比較,求得dp[0][j]要升到第j的高度時所要的花費
4、對第二點及以後的每一點進行更新。dp[i][j]第i+1點到高度j時的前i+1個總的花費
在這裡插入圖片描述
5、找到更後最後一個點到任意高度的最小值便為答案

AC程式碼:

#include<string.h>
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=2e3+10;
int n,k;
int a[M],b[M],c[M];
int dp[M][M],e[M][M];///用陣列下標進行離散化,表示某位置最小的花費
bool cmp(int x,int y)
{
    return x>y;
}
int main()
{
    cin>>n;
    for (int i=0; i<n; i++)
        cin>>a[i],b[i]=c[i]=a[i];
    sort(b,b+n);
    for (int i=0; i<n; i++)
        dp[0][i]=abs(b[i]-a[0]);
    for(int i=1; i<n; i++)//列舉第幾座山峰
    {
        k=dp[i-1][0];
        for (int j=0; j<n; j++)///列舉山峰到達離散化後某高度
        {
            k=min(k,dp[i-1][j]);
            dp[i][j]=k+abs(b[j]-a[i]);
        }
    }
    sort(c,c+n,cmp);
    for (int i=0; i<n; i++)
        e[0][i]=abs(c[i]-a[0]);
    for(int i=1; i<n; i++)
    {
        k=e[i-1][0];
        for (int j=0; j<n; j++)
        {
            k=min(k,e[i-1][j]);
            e[i][j]=k+abs(c[j]-a[i]);
        }
    }
    int ans=dp[n-1][0];
    for (int i=0; i<n; i++)
        ans=min(ans,min(dp[n-1][i],e[n-1][i]));
    cout<<ans<<endl;
    return 0;
}

相關文章