牛客练习赛67 D.牛妹爱数列

牛客练习赛67 D.牛妹爱数列

题目链接

题目描述

牛妹正在玩一个数列
他手里有一个长度为n的序列a,保证它是一个01序列,并执行以下两种操作:
1.单点修改:将位置x上的数翻转(0变1,1变0);
2.前缀修改:将位置1~x上的数翻转(每个数都0变1,1变0)。
他现在想要最小化翻转次数,使得数列上的所有数都变为0。

输入描述:

第一行,输入一个数 n n n
第二行,输入 n n n 个数,第i个数表示 a i a_i ai

输出描述:

输出最小翻转次数。

示例1

输入

10
1 0 1 1 0 0 0 1 0 0

输出

3

简单 DP~
比赛时一直以为是前缀和,吐了,还是 DP 学得太差,用 d p [ x ] [ 0 / 1 ] dp[x][0/1] dp[x][0/1] 表示 1-x 位置全部变成 0/1 的最少操作次数,则有状态转移方程:

  • a [ i ] = 1 a[i]=1 a[i]=1
    d p [ i ] [ 0 ] = m i n ( d p [ i − 1 ] [ 0 ] + 1 , d p [ i − 1 ] [ 1 ] + 1 ) ; dp[i][0]=min(dp[i-1][0]+1,dp[i-1][1]+1); dp[i][0]=min(dp[i1][0]+1,dp[i1][1]+1);
    d p [ i ] [ 1 ] = m i n ( d p [ i − 1 ] [ 0 ] + 1 , d p [ i − 1 ] [ 1 ] ) ; dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1]); dp[i][1]=min(dp[i1][0]+1,dp[i1][1]);
  • a [ i ] = 0 a[i]=0 a[i]=0
    d p [ i ] [ 0 ] = m i n ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] + 1 ) ; dp[i][0]=min(dp[i-1][0],dp[i-1][1]+1); dp[i][0]=min(dp[i1][0],dp[i1][1]+1);
    d p [ i ] [ 1 ] = m i n ( d p [ i − 1 ] [ 0 ] + 1 , d p [ i − 1 ] [ 1 ] + 1 ) ; dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1]+1); dp[i][1]=min(dp[i1][0]+1,dp[i1][1]+1);

最后直接输出 d p [ n ] ] [ 0 ] dp[n]][0] dp[n]][0] 即可,AC代码如下:

#include
using namespace std;
typedef long long ll;
const int N=1e5+5;
int a[N],dp[N][2],n;
int main()
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>a[i];
    for(int i=0;i<n;i++){
        if(a[i]==1){
            dp[i][0]=min(dp[i-1][0]+1,dp[i-1][1]+1);
            dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1]);
        }else{
            dp[i][0]=min(dp[i-1][0],dp[i-1][1]+1);
            dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1]+1);
        }
    }
    cout<<dp[n-1][0];
}

你可能感兴趣的:(动态规划,牛客)