一个简单的dp,状态转移方程也很容易写出。
我用了两个数组保存dp状态,dp0[i]是把前i个变成0最少用的步数,dp1[i]则是把前i个全部变成1的个数。
对于dp0[i],我们可以从dp1[i-1]和dp0[i-1]转移过来,即
1)dp0[i]=dp1[i - 1] + 1,将前i-1个或者前i个全部翻转一下,增加一次转换次数。
2)dp0[i]=dp0[i - 1] + a[i],前i-1个点都为0,于是只要确定i这个点要不要翻转就行了
dp1[i]同理,得到如下方程
dp0[i] = min(dp1[i - 1] + 1, dp0[i - 1] + a[i])
dp1[i] = min(dp0[i - 1] + 1, dp1[i - 1] + (a[i] == 0))
最后代码实现

#include<iostream>
#include<algorithm>
using namespace std;
int dp0[100010],dp1[100010];
int n,a[100010];
int main() {
    cin >> n >> a[0];
    dp0[0] = (a[0] == 1);
    dp1[0] = 1 - dp0[0];
    for (int i = 1; i < n; ++i){
        cin >> a[i];
        dp0[i] = min(dp1[i - 1] + 1, dp0[i - 1] + a[i]);
        dp1[i] = min(dp0[i - 1] + 1, dp1[i - 1] + (a[i] == 0));
    }
    cout << dp0[n - 1];
    return 0;
}

另外,比赛写代码的时候还想到了贪心,从末尾贪心到前面,当只有一个点要修改的时候,进行单点修改,当有多个点修改时,将前面全部翻转,可以证明满足无后效性,这里就不给证明了。