SJTU OJ 1282 修路 題解

來源:互聯網
上載者:User

標籤:des   style   os   檔案   資料   io   

1282. 修路

Description

蹦蹦跳跳結束後,cxt回頭看看自己走過的路坑坑窪窪的,心中非常不爽,他表示要把這段路的路面高度修成單調上升的或者單調下降的,整條路可以看成 N段,N個整數A1,…..,An(1<=n<=2000)依次描述了每一段路的高度(0<=Ai<=1000000000)。 希望找到一個恰好含N個元素的不上升或不下降的序列B1,……,Bn,作為修過的路中每個路段的高度。

由於將每一段路墊高或挖低一個單位消耗的體力相同,於是可以表示為:

|A1-B1|+|A2-B2|+…..+|An-Bn|

請你計算一下,要修好這段道路,最少消耗多少體力。消耗的總體力不會超過2^31-1

Input Format

輸入檔案的第一行僅有一正整數N,以下的N行每行一個整數Ai,表示路面的高度。

Output Format

輸出檔案僅有一個正整數,表示如果把路修成高度不上升或不下降的最小花費

Sample Input
71324539
Sample Output
3
Hint

將第一個高度為3的路段的高度減少為2,將第二個高度為3的路段的高度增加到5,總花費為|2-3|+|5-3|=3,並且各路段的高度為一個不下降序列 1,2,2,4,5,5,9。


================================

題解本文

================================

  1. 題目分析

    1. 這是一道動態規劃題目,求最小花費使道路變成不嚴格單調遞增或不嚴格單調遞減,資料大小用int即可。

    2. 修改後的值肯定是原來數列裡的值。‘
    3. 對於結果來說,每一段都是不嚴格單調遞增或不嚴格單調遞減的數列。
  2. 解決方案
    1. 我們需要把一個數列排序(上升或下降都可以),來作為計算時的參考標準。(為什麼需要這個標準呢?因為上面提到修改後的值肯定是原來粗線過的,而最終的結果是不嚴格單調的,所以與排序後的數列比較就很方便)
    2. 我們需要對輸入的數列進行排序但不希望影響後來的操作,所以顯然我們得把原數列複製一遍再排序。
    3. 樸素的思想就是我們依次把排序後的數列的某個數當作是我們最終修正後的路面的結束值(即最大或最小),因為當作參考的數列是排序過的,所以能保證結果滿足題意,即不嚴格單調。
    4. 用f[i][j] 表示將原數列的前i個元素改為不嚴格單調且第i個元素改為排序後數列的第j個元素時所花費的最小的體力。用a表示原數列,b表示排序後的數列。得到狀態轉移方程f[i][j]=min{f[i-1][k]+abs(b[j]-a[i])}(1<=k<=j)
    5. 最後的結果就是從f[i][j]中找到最小值。
  3.     #include<iostream>    #include<cmath>    #include<algorithm>    using namespace std;         int n,ans=1<<30,a[2005],c[2005],f[2005][2005],g[2005][2005];         void init()    {        cin>>n;        for(int i = 1; i <= n ; ++i)        {            cin >> a[i];            c[i]=a[i];        }        sort(c+1,c+n+1);    }    void sol()    {        for(int i = 1; i <= n; ++i)        {            for(int j = 1; j <= n; ++j)            {                f[i][j] = g[i-1][j] + abs(a[i]-c[j]);                if(j == 1) g[i][j] = f[i][j];                else g[i][j] = min(f[i][j],g[i][j-1]);            }        }        for(int i = 1; i <= n; ++i)        ans = min(ans ,f[n][i]);    }         int main()    {        init();        sol();//算一遍遞增        for(int i = 1; i <= n/2 ; ++i)            swap(c[i],c[n-i+1]);        sol();//算一遍遞減        cout<<ans;    }



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.