標籤:
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 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
71324539
Sample Output
3
Source
USACO 2008 February Gold
題意:
給定一個序列,以最小代價將其變成單調不增或單調不減序列,這裡的代價看題目公式。
思路:
很容易想到是DP。
1.
對前i個序列,構成的最優解其實就是與兩個參數有關。一個是這個序列處理後的最大值mx,和這個序列處理的代價值cost。
顯然最大值mx最小最好(這樣第i+1個值可以不花代價直接接在其後面的可能性更大),cost最小也最好(題意要求),但是兩者往往是魚和熊掌。
用dp[i][j]表示:前i個數構成的序列,這個序列最大值為j,dp[i][j]的值代表相應的cost。
所以狀態轉移方程如下:
dp[i][j]=abs(j-w[i])+min(dp[i-1][k]);(k<=j)
這個表格是根據轉移方程寫出來的dp數組。
再仔細看一下轉移方程:dp[i][j]=abs(j-w[i])+min(dp[i-1][k]);(k<=j)
右邊沒填充的是因為填充的數字肯定比前面的數字大,無用,因為在求min( dp[i-1][k] )時,是求最小值,既然更大,則最小值時無需考慮。
又從表格中可以看出:
dp[i][j]=abs(j-w[i])+min(dp[i-1][k]);(k<=j)這裡的k無需從1遍曆到j。
只要在對j進行for迴圈的時候不斷更新一個dp[i-1][j]的最小值mn=min(mn,dp[i-1][j]),
然後對dp[i][j]=abs(j-w[i])+mn即可;
這樣改進之後即可從本來的時候時間複雜度O(NMM)改進為O(NM);
但是,這裡的m是A[i]的最大值,顯然TLE。
所以必須用離散化思想改進,因為N=2000。遠小於A[i]的最大值。
離散化:將序列排序一下,然後用位置的前後關係來制定其值,這樣時間複雜度變成O(N^2).
最後是這題資料有bug,只需要求不減序列即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<map> 6 #include<set> 7 using namespace std; 8 #define inf 1<<30 9 #define N 200610 int n;11 int a[N];12 int b[N];13 14 int dp[N][N];15 bool cmp(int a,int b){16 return a>b;17 }18 int main()19 {20 while(scanf("%d",&n)==1){21 for(int i=1;i<=n;i++){22 int x;23 scanf("%d",&x);24 a[i]=b[i]=x;25 }26 27 28 sort(b+1,b+1+n);29 memset(dp,0,sizeof(dp));30 for(int i=1;i<=n;i++){31 dp[1][i]=abs(a[1]-b[i]);32 }33 //dp[1][tmp]=tmp;34 for(int i=2;i<=n;i++){35 int tmp=dp[i-1][1];36 for(int j=1;j<=n;j++){37 tmp=min(tmp,dp[i-1][j]);38 dp[i][j]=tmp+abs(a[i]-b[j]);39 }40 }41 int ans1=inf;42 for(int i=1;i<=n;i++){43 ans1=min(ans1,dp[n][i]);44 }45 46 //printf("%d\n",ans1);47 48 memset(dp,0,sizeof(dp));49 sort(b+1,b+1+n,cmp);50 51 for(int i=1;i<=n;i++){52 dp[1][i]=abs(a[1]-b[i]);53 }54 for(int i=2;i<=n;i++){55 int tmp=dp[i-1][1];56 for(int j=1;j<=n;j++){57 tmp=min(tmp,dp[i-1][j]);58 dp[i][j]=tmp+abs(a[i]-b[j]);59 }60 }61 int ans2=inf;62 for(int i=1;i<=n;i++){63 ans2=min(ans2,dp[n][i]);64 }65 printf("%d\n",min(ans1,ans2));66 67 68 }69 return 0;70 }View Code
poj 3666 Making the Grade(dp)