dp01序列变化
链接:https://ac.nowcoder.com/acm/contest/6885/D
来源:牛客网
他手里有一个长度为n的序列a,保证它是一个01序列,并执行以下两种操作:
1.单点修改:将位置x上的数翻转(0变1,1变0);
2.前缀修改:将位置1~x上的数翻转(每个数都0变1,1变0)。
他现在想要最小化翻转次数,使得数列上的所有数都变为0。
输入描述:
第一行,输入一个数n。
第二行,输入n个数,第i个数表示aia_iai。
输出描述:
输出最小翻转次数。
示例1
备注:
数据保证1≤n≤1e5,。
表示到了第i个位置,把前面的都变成0的最小操作数
表示到了第i个位置,把前面的都变成1的最小操作数
如果当前位置上a[i]=1,则:
dp[i][0]=min(dp[i - 1][0] + 1, dp[i - 1][1] + 1),我们可以将a[i]单独翻转,也可以将这前缀1一起翻转;
dp[i][1] = min(dp[i - 1][1], dp[i - 1][0] + 1),我们可以将前缀00翻转,然后把a[i]a[i]拼上去。
如果当前位置上a[i]=0,则:
dp[i][0] = min(dp[i - 1][0], dp[i - 1][1] + 1),我们可以将前缀1翻转,然后把a[i]拼上去;
dp[i][1] = min(dp[i - 1][0] + 1, dp[i - 1][1] + 1),我们可以将a[i]a[i]单独翻转,也可以将这前缀0一起翻转;
答案记为min(dp[n][0],dp[n][1])。
#include<iostream> #include<algorithm> using namespace std; const int maxn=1e6+100; int dp[maxn][2];//dp[i][0]前面都变成0最少的操作次数 int a[maxn];//dp[i][1]前面都变成1最少的操作次数 int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; } if(a[1]==0){ dp[1][0]=0; dp[1][1]=1; } else{ dp[1][0]=1; dp[1][1]=0; } for(int i=2;i<=n;i++){ if(a[i]==0){ dp[i][1]=min(dp[i-1][1]+1,dp[i-1][0]+1); dp[i][0]=min(dp[i-1][0],dp[i-1][1]+1); }else{ dp[i][1]=min(dp[i-1][1],dp[i-1][0]+1); dp[i][0]=min(dp[i-1][0]+1,dp[i-1][1]+1); } } cout<<min(dp[n][0],dp[n][1]+1)<<endl; }