正所谓万物皆可dp
复杂度【O(2n)】
烧脑Dp题解奉上。
定义dp方程dp1[i][2] (0表示从前往后到第i位置为止,全都是0; 1表示从前往后到第i位置位置全是1? 并不是哦,1表示第i位置往前都是连续的1, 即00001111这种,i=8的位置往前都是连续的1)为i位置处理完后的最小操作次数。
dp2[i][2]同理, 只是方向反一下,是从后往前;
好,定义完了,开始给出递推方程式:

if (str[i] == '1')
        {
            dp1[i][1] = min(dp1[i - 1][1], dp1[i - 1][0]);
            dp1[i][0] = dp1[i - 1][0] + 1;
        }
        else
        {
            dp1[i][1] = min(dp1[i - 1][1] + 1, dp1[i - 1][0]);
            dp1[i][0] = dp1[i - 1][0];
        }

对于当前i是1的时候:
最小的dp1[i][1]要么是连着前面的连续1, 要么就是连着前面的全0;
最小的dp1[i][0]只能是连着前面的全0,因为按定义上来讲,不可能连着连续1来;
对于i是0的情况:
最小的dp[i][1]中,我们将0去掉,然后连接dp[i -1][0]或者dp[i - 1][1]就可以了;
对于dp[i][0],直接连接上前面的全0;


dp2[i][j]的推到是同理,然后问题就迎刃而解了。
解决好dp后,只需要遍历字符串的每一个位置;
对于每个位置有4中情况;
要么前面全零,后面连续的1;
要么前面全零, 后面全零;
要么前面连续1, 后面全零;
要么前面连续1,后面全零;

mi = min(min(min(dp1[i - 1][0] + dp2[i][0], dp1[i - 1][0] + dp2[i][1]),  min(dp1[i - 1][1] + dp2[i][0], dp1[i - 1][1] + dp2[i][1])), mi);

下面给出AC代码:

#include <iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define lowbit(n) n&(-n)
using namespace std;
#define dbg(x) cout << #x << " = " << x << endl;
const long long  MAXN = 2e6;
typedef long long ll;
int t;
ll n, m, k;
char str[MAXN];
int dp1[MAXN][2], dp2[MAXN][2];
int main(int argc, char const *argv[])
{
    int n;
    cin >> n;
    cin >> (str + 1);
    int mi = 0x3f3f3f;
    for (int i = 1; i <= n; i++)
    {
        if (str[i] == '1')
        {
            dp1[i][1] = min(dp1[i - 1][1], dp1[i - 1][0]);
            dp1[i][0] = dp1[i - 1][0] + 1;
        }
        else
        {
            dp1[i][1] = min(dp1[i - 1][1] + 1, dp1[i - 1][0]);
            dp1[i][0] = dp1[i - 1][0];
        }
    }
    for (int i = n; i >= 1; i--)
    {
        if (str[i] == '1')
        {
            dp2[i][1] = min(dp2[i + 1][1], dp2[i + 1][0]);
            dp2[i][0] = dp2[i + 1][0] + 1;
        }
        else
        {
            dp2[i][1] = min(dp2[i + 1][1] + 1, dp2[i + 1][0]);
            dp2[i][0] = dp2[i + 1][0];
        }
    }
    for (int i = n; i >= 1; i--)
    {
        mi = min(min(min(dp1[i - 1][0] + dp2[i][0], dp1[i - 1][0] + dp2[i][1]),  min(dp1[i - 1][1] + dp2[i][0], dp1[i - 1][1] + dp2[i][1])), mi);
    }
    cout << mi << endl;
    return 0;
}