Codeforces Round 522 Div2 C. Playing Piano
一、題意
地址: http://codeforces.com/contest/1079/problem/C
題意:輸入鋼琴的曲譜,每個調可以使用一個手指頭按一下,手指頭編號1到5。
要求1:相鄰的兩個調,調更高時,需要使用編號更高的指頭。
要求2:相鄰的兩個調,相等時,兩個指頭需要不同。 求輸出一直彈奏的指法。
二、分析
由於每個位置頂多有5個指法,我們可以計算出每個位置的5個指法是否可行。
從左右到看,一個位置的某個指法是否可行,可以由上個位置推匯出來。
所以這是典型的動態規劃題,而且是初級 DP 題。
展開來看,依舊是從左到右。
第一個位置任何一個手指都可以按。
第二個位置需要根據第一個調的值以及指法來計算。
具體計算方法是第二個位置的某個指法,我們迴圈上個位置的所有指法,判斷上個位置指法是否合法,以及能否滿足題目的兩個要求。滿足了當前指法就是合法的。
由於題意要求輸出其中一個路徑,合法的時候我們可以儲存這個合法指法是從哪個指法推導過來的。
這樣從左到右就可以計算出最後一個位置的所有合法指法。
如果最後一個位置存在合法指法,逆向推導即可計算出合法路徑。
預設情況下,複雜度是 O(n * 5 * 5)
在從左到有推導的時候,我們可以得出這樣一個結論: 如果b是大於上個位置的合法指法,那麼大於b的都是合法的。 因為最大的指法大於b,所以最大的指法肯定也是合法的。
因此,我們可以根據最大的指法快速判斷當前指法是不是合法的。
例如,對於第 2 個位置 ,合法指法是 1,2,3
。
第 3 個位置小於第 2 個位置,我們可以快速得到第3個位置的 1
是合法指法。
因為 1
可以從 2
和 3
推導得到。更簡單點, 1
可以從最大合法值 3
推導得到, 2
也可以從最大合法值 3
推導得到 。
由此,我們可以維護一個上個位置的最大合法值和最小合法值(單點最值,不是區間),從而少一次迴圈,複雜度降為 O(n * 5)
。
本文首發於公眾號:天空的程式碼世界,微信號:tiankonguse-code。