input
讀入一共有兩行,第一行只有乙個正整數數n,表示鋼琴床有n個部分。output第二行由乙個01串組成
n≤1000000
保證01串的長度為n
輸出乙個正整數表示肥豬最少要拿走的部分的數量samples
input
3111
output
0input copy
3101
output
1input copy
6010011
output
1
source
2020廣東工業大學新生賽
很不錯,比賽的時候沒寫出來,當時壓根沒向dp方面靠,賽後搜了題解,看了大佬們dp的思路,哇,好生巧妙啊?,理解起來也不難,隨即寫此篇部落格記錄一下子吧。
解題思路:
不衝突的狀態可分為以下幾種 :
① 全0狀態:00000000
00000000
000000
00② 全1狀態:111111111
111111111
111111
111③ 01分居左右兩側:000000111111or
11111100000
000000111111 \ or \ 11111100000
000000
1111
11or
1111
1100
000④ 010式分步:0000111111110000000
0000111111110000000
000011
1111
1100
0000
0稍微歸納一下,課將上述所有情況歸納為一種狀態:即 010
01001
0 式分步狀態
我們用 a
aa 來表示左側的所有 0
00,a
aa 的值為左側 0
00 的個數;
相應的我們用 b
bb 來表示中間的所有 1
11,b
bb 的值為中間 1
11 的個數。
同理,c
cc 表示右側的所有 0
00,c
cc 的值表示右側 0
00 的個數。
用 a bc
abcab
c 即可表示合法的所有狀態。(a,b
,c
a,b,c
a,b,
c的值可以為 000)
接下來我們進行狀態表示的處理,dp[i][0] 表示當前所列舉的位置位於合法狀態的左側,相應的dp[i][1]和dp[i][2]分別表示位於中間和右側。三者的值表示前 i
ii 項變為合法狀態所需刪除的最小次數。
最後就是狀態轉移了,位於左側的狀態只能由左側轉移而來,位於中間狀態可有左側或中間轉移而來,位於右側可有中間和右側轉移而來。
寫出狀態轉移方程即:
//當前位置是0
dp[i][0
]= dp[i-1]
[0];
///0位於左側 /*當前狀態位於中間位置,上乙個狀態一定是處於左側和中間這兩種狀態,則狀態轉移不難寫出*/
dp[i][1
]=min(dp[i -1]
[0],dp[i -1]
[1])
+1;///0位於中間位置,需要刪去
dp[i][2
]=min(dp[i -1]
[1],dp[i -1]
[2])
;///0位於右側,無需刪除
//當前位置是1
dp[i][0
]= dp[i -1]
[0]+
1;///1位於左側,需要刪除
/*當前狀態位於中間位置,上乙個狀態一定是處於左側和中間這兩種狀態,則狀態轉移不難寫出*/
dp[i][1
]=min(dp[i -1]
[0],dp[i -1]
[1])
;///1位於中間位置,無需刪除
dp[i][2
]=min(dp[i -1]
[1],dp[i -1]
[2])
+1;///1位於右側,需刪除
上完整**
#include
using
namespace std;
typedef
long
long ll;
int dp[
1000010][
3];int
main()
else
} cout<<
min(dp[n][0
],min(dp[n][1
],dp[n][2
]))
}
肥豬的鋼琴床
題目描述肥豬很喜歡睡懶覺,與此同時肥豬十分喜歡買各種各樣神奇的床。我們假設0表示某乙個位置是凹下去的,1表示某乙個位置是凸起來的。那麼0 100111 01111000 11100 都是肥豬喜歡的鋼琴床,因為所有凸起來的部分都是連續的 輸入詳情 讀入一共有兩行,第一行只有乙個正整數數n,表示鋼琴床有...
天天的鋼琴(數論)
題目描述 天天開始彈奏鋼琴了。他的鋼琴由 n個琴鍵組成,每個鍵有乙個權值xi,當天天開始彈琴時,他同時按k個不同的鍵。但是這個鋼琴十分古怪,在他同時按了k個鍵之後,我們只能聽到具有最大權值的那個鍵。現在天天準備試試這個鋼琴k個鍵的所有組合,他想要知道將要聽到琴聲的權值和。因為結果會很大,所以輸出mo...
哪個在搖我的床?
哪個在搖我的床?早上睡得正爽,硬是被搖醒,真是太氣了!憤然睜開眼,周圍卻沒有人,不過,房間裡到處都在搖晃,是我沒休息好?眼花了,頭暈了?確實我是在隨著床擺動,從窗戶看出去,看到六樓陽台上的花盆也在蹦蹦跳跳,我一下清醒了許多 我正在經歷 還好,我的床就在牆角擺著,應該這個部分比較安全,還是靜靜地躺在床...