[四連測(一)]電話線路
題目描述
最近,約翰的奶牛們越來越不滿足於牛棚裡一塌糊塗的電話服務,於是,她們要求
約翰把那些老舊的電話線換成效能更好的新電話線。新的電話線架設在己有的n根
電話線杆上,第i根電話線的高度為hi, ( 1 <= hi<= 100)。電話線總是從一根電話
線杆的頂端被弓}到相鄰的那根的頂端,如果這兩根電話線杆的高度hi和hj不同,那
麼約翰就必須支付c * |hi - hj|的費用,當然,你不能行動電話線杆,只能按照原有
的順序在相鄰杆間架設電話線。
加高某些電話線杆能減少架設電話線的總費用,儘管這項工作也需要支付一定的
費用。更準確的說,如果他把一根電話線杆加高x米的話,他需要付出x^2費用。
請你幫約翰計算一下,如果合理的進行這兩項工作,他最少要在這個電話線改造
工程中花多少錢
輸入
第一行輸入兩個數n和c, 含義如上
接下來n行,每行一個整數hi
輸出
輸出約翰完成電話線改造工程需要花費的最小費用
樣例輸入
5 2
2
3
5
1
4
樣例輸出
15
資料範圍
N <= 100000, C <= 100, Hi < 100,答案不超過maxlongint。
解題思路
首先,確定題型:DP(感覺好難啊,看到DP就怕了)既然是DP,那該怎麼定義呢?首先,第一維i肯定是第幾根電線杆。這是毋庸置疑的,那麼第二維呢?這裡有幾個選擇。
(一)第二維放第i根電線子改變後的高度。
(二)第二維放第i根電線子所增加的高度。
此題想來只能用二維DP,這樣的資料範圍三維是絕對會爆的,於是我們就不考慮三維這樣的情況。(然而考試時候深陷其中無法自拔,簡單的二維都想不到了。。。。)
由於知道每根電線杆的原高度,我們用j表示新的高度(即第二維放第i根電線杆的高度)。那麼便可以求出從a[i]到j所需要的費用,這樣是比較好算的,並且儲存了第i根電線杆j高時的最優狀態,後面算高度差時也比較好用。
這樣DP[i][j]就表示第i杆電線杆高度為j時所花的最小費用。
狀態轉移方程:
然而。。。其中有三個變數i,j,k。還不是用三重循壞不也爆了?這個時候,就要開始進行優化了。我們從狀態轉移方程中入手,min後面的那一塊是一個定值,我們可以不用管。|j-k|
於是,c * |j - k|就可以化了。於是又得到兩種不同情況的狀態轉移方程
我們可以知道j其實在列舉更值得時候是一個定值,我們於是就可以將它提出來。做到簡化的目的,你也許會想,這樣依舊還是要爆。這時候我們最好就是要同時將j,k都枚舉了。這樣才能夠不超時。事實上這是可以做到的。我們通過優化列舉j就可以達到效果
進行預處理,第一個電線杆達到的j高度的花費就是
首先就要確定列舉的方向,可以清楚的是,這兩個分類討論的情況是需要分開進行處理的。那麼第一個(k>=j,意思是如果k只能取j到100的值)就需要倒著進行列舉。因為這樣就可儲存中間的min,同理,第二個(k<j)正著列舉。
我們用兩個變數,在列舉過程中,儲存最小值,更新DP值。更新完之後也儲存這一個情況的最小值。可能有點抽象。具體看一下程式碼
for (int i = 2;i <= n; i++){//列舉每一個電線杆,第一個電線杆進行了預處理
int minn = inf ,minn1 = inf;
for (int j = 1 ;j <= a[i] ;j ++ ){//這一段是k<j的情況,由於j是不可能取到小於a[i]的值,因此這裡就是求一個最小值
minn = min((dp[i - 1][j] - c * j) , minn);
}
for (int j = a[i] ; j <= 100 ; j ++ ){//k<j的情況,在這裡我們就需要更新DP的值
minn = min(minn,dp[i - 1][j] - c * j);
dp[i][j] = min(dp[i][j],minn + c * j + (j - a[i]) * (j - a[i]));
}
for (int j = 100;j >= a[i]; j -- ){//k > j的情況,在這裡我們需用另一個變數,儲存最小值。並且更新DP的值。
minn1 = min(minn1, (dp[i - 1][j] + c * j));
dp[i][j] = min(dp[i][j],minn1 - c * j + (j - a[i]) * (j - a[i]));
}
}
完整程式碼就不放了,其實除了輸入輸出與預處理,就這一部分程式碼了。
總結
DP總覺得還是比較難想啊。考試時候根本不好弄DP,縱使我想出了DP,也還是想不到優化的方法。此題的關鍵點可以說不在DP,而在優化。對於DP列舉j順序的改變可以說很難想了。但實現卻是不難,想到一種簡單的狀態轉移方程就顯得尤其重要,回想了一下,在我想狀態轉移方程的時候,基本上都轉移不了,根本無法表示,更不用說做題了,這就需要我去抓住題目中的本質資訊就比如說這道題,題目中編號肯定是有的,同時高度又決定了值,所以我們最好將高度定下來,於是高度變成了j來進行列舉。而優化的步驟則抓住了不同DP狀態的條件,改變順序。有些題,拿到題還是要判斷演算法,用那樣的一種思路去進行計算。