肥猪的钢琴床(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;
}

猜你喜欢

转载自blog.csdn.net/Stevenwuxu/article/details/110778480