zoukankan      html  css  js  c++  java
  • 牛客练习赛67 D-牛牛爱数列(DP)

    题目链接:https://ac.nowcoder.com/acm/contest/6885/D
    CSDN食用链接:https://blog.csdn.net/qq_43906000/article/details/108019695

    题目描述

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

    输入描述:
    第一行,输入一个数n。
    第二行,输入n个数,第i个数表示(a_i)

    输出描述:
    输出最小翻转次数。

    输入
    10
    1 0 1 1 0 0 0 1 0 0
    输出
    3

    说明
    样例解释:
    第一次使用(1)操作, 把2改掉: 1 1 1 1 0 0 0 1 0 0
    第二次使用(2)操作, 把1-4全部改掉: 0 0 0 0 0 0 0 1 0 0
    第三次使用(1)操作, 把8改掉: 0 0 0 0 0 0 0 0 0 0
    备注:
    数据保证(1le nle 10^5,0le a_ile 1)

    emmm,我们可以考虑从前往后DP,其DP状态可以考虑设为(dp[n][0/1]),其中,dp[i][0]表示将前缀(i)全部化为0的最小步数,dp[i][1]则表示将前缀化为1的最小步数。
    那么我们很容易得出其转移方程了。只不过需要注意的是最后取答案的时候由于是将整个序列变为0,所以dp[n][1]要加上1再和dp[n][0]进行比较。

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int mac=1e5+10;
    int dp[mac][2];//0:change the prefix to 0,1:change the prefix to 1;
    int a[mac];
    
    int main(int argc, char const *argv[])
    {
        int n;
        scanf ("%d",&n);
        for (int i=1; i<=n; i++)
            scanf ("%d",&a[i]);
        memset(dp,0x3f3f,sizeof dp);
        dp[1][0]=(a[1]==1);
        dp[1][1]=(a[1]==0);
        for (int i=2; i<=n; i++){
            if (a[i]==0){
                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);
            }
            else {
                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]);
            }
        }
        printf("%d
    ",min(dp[n][0],dp[n][1]+1));
        return 0;
    }
    
  • 相关阅读:
    异常
    一线互联网大厂,内推吧!
    node-sass 安装失败的解决办法
    上下文执行栈
    1像素边框
    babel需要这样配置
    【webpack】中enforce的使用方法
    【webpack】中resolveLoader的使用方法
    【webpack】中的devtool的使用方法
    【webpack】中splitChunk的使用方法
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13507947.html
Copyright © 2011-2022 走看看