肥豬的鋼琴牀(dp好題)

肥豬的鋼琴牀

題目傳送門:

肥豬的鋼琴牀

題目大意:

給你一個01序列,要求所有的1連在一起,你可以把0改成1,你也可以把1改成0。問最少的操作次數是多少。

思路:

由題目我們馬上就能想到最後的序列一定是0000111110000這種形式的。明顯分成了三段,第一段的0,第二段的1,第三段的0。
每個位置都可能是這三段中的一段。我們用dp [ i ] [ 0 ],dp [ i ] [ 1 ],dp [ i ] [ 2 ]表示位置i是不同段中的最少操作的次數。
可以得到遞推式
dp [ i ][ 0 ] = dp [ i - 1 ] [ 0 ] + a[ i ] - 0
( 當前這個位置是第一段時,上一個位置也必然是第一段)



dp [ i ][ 1 ] = min( dp [ i - 1 ][ 0 ]+ 1 - a[ i ] ,dp [ i -1 ][ 1 ] + 1 - a[ i ] )
(當這個位置位於第二段時,上一個位置可能是第一段也可看個是第二段)

dp [ i ][ 2 ] = min( dp[ i-1 ][ 1 ] + a[ i ] - 0 , dp[ i-1 ][ 2 ]+ a[ i ] - 0)
(當這個位置位於第三段時,上一個位置可能是第二段,也可能是第三段)

AC Code

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N],dp[N][3];
int main()
{
   
   
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%1d",&a[i]);
    for(int i=1;i<=n;i++)
    {
   
   
        dp[i][0]=dp[i-1][0]+a[i];
        dp[i][1]=min(dp[i-1][0]+1-a[i],dp[i-1][1]+1-a[i]);
        dp[i][2]=min(dp[i-1][2]+a[i],dp[i-1][1]+a[i]);
    }
    int res=min(dp[n][0],dp[n][1]);
    res=min(res,dp[n][2]);
    printf("%d\n",res);
    system("pause");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章