D-牛妹爱数列_牛客练习赛67 (nowcoder.com)
问题描述:给01数组,可以进行一下两种操作:
求最小的翻转次数,使数列上的数全部变为0。
思路:
最优,满足最优子结构,无后效性,子问题重叠,用dp。
找状态:从1到当前位置 全0/1时的最小花销。
转移方程:
ai = 1
时
F ( i , 0 ) = m i n ( F ( i − 1 , 0 ) + 1 , F ( i − 1 , 1 ) + 1 ) F ( i , 1 ) = m i n ( F ( i − 1 , 0 ) + 1 , F ( i − 1 , 1 ) ) F(i,0) = min(F(i-1,0)+1, F(i-1,1)+1) \\ F(i,1) = min(F(i-1,0)+1, F(i-1,1)) F(i,0)=min(F(i−1,0)+1,F(i−1,1)+1)F(i,1)=min(F(i−1,0)+1,F(i−1,1))
ai = 0
时
F ( i , 0 ) = m i n ( F ( i − 1 , 0 ) , F ( i − 1 , 1 ) + 1 ) F ( i , 1 ) = m i n ( F ( i − 1 , 0 ) + 1 , F ( i − 1 , 1 ) + 1 ) F(i,0) = min(F(i-1,0), F(i-1,1)+1) \\ F(i,1) = min(F(i-1,0)+1, F(i-1,1)+1) F(i,0)=min(F(i−1,0),F(i−1,1)+1)F(i,1)=min(F(i−1,0)+1,F(i−1,1)+1)
状态表示:
F(i,j)
表示从1到当前位置全转为j的最小花销。
目标:
F ( N , 0 ) F(N,0) F(N,0)
边界:无。
代码:
int f[N][2];
void inpfile();
void solve() {
int n; cin>>n;
rep(i,1,n) {
int v; cin>>v;
if(v) {
f[i][0] = min(f[i-1][0] + 1, f[i-1][1] + 1);
f[i][1] = min(f[i-1][0] + 1, f[i-1][1]);
} else {
f[i][0] = min(f[i-1][0], f[i-1][1] + 1);
f[i][1] = min(f[i-1][0] + 1, f[i-1][1] + 1);
}
}
cout<<f[n][0];
}