求01反转次数
题目描述
Yuilice最近给学生们上了一节动态规划的课程,为了让各位同学了解到动态规划的核心内容是划分阶段与建立状态转移方程,于是他出了这一道题。
Yuilice会给各位同学一个字符串S,这个字符串S只会由字符0与字符1组成,Yuilice可以对这个字符串进行一些操作,操作的内容如下。
- Yuilice可以选中下标为i(1≤i≤S.length)的字符,将位于下标i后的所有字符i≤j≤S.length全部变为相反的数,例如0全部变成1,1全部变成0。
现在,Yuilice想知道,他最少需要几次操作,才可以将字符串S变为不递减的字符串?
输入格式
第一行输入一个正整数t(1≤t≤104),代表接下来有t组样例测试。
随后t行,每行给出一个数字n(1≤n≤105),代表字符串S的长度。
输出格式
每一组样例,输出一个整数代表其最少操作次数
样例 #1
样例输入 #1
5
1
1
3
101
5
10101
10
1010101010
7
0001000
样例输出 #1
0
2
4
9
1
提示
NOTE
第一组样例当中,字符串本身便不是递减的。
第二组样例当中,我们需要在i=2的时候转变字符串后两个字符变为10,于i=3的时候转变后一个字符为1,最后将字符串变为111则可完成。
My idea:
-
正状态,在正状态下,所有字符都是原样的,比较也拿原本的数值比较,经过一次翻转变成反状态。
-
反状态,在反状态下,所有字符都是翻转过来的,0当1算,1当0算,拿反过来的数值进行比较,经过一次翻转变成正状态。
-
阶段 :我们只需要枚举1~n每两个数值是否成非递减,比较的时候参考正反状态分割成两个阶段,按照正反状态的规则来比较,如果不成非递减顺序,那么我们就给他翻转1次,记录次数,最后输出即可。
-
状态转移方程:设F为正反状态的标记,F为true的时候代表是正,F为false代表是反。
F=True
- S[i]<=S[i]+1,DP[i+1]=DP[i];
- S[i]>S[i]+1,DP[i+1]=DP[i]+1;
F=False
- S[i]>=S[i]+1,DP[i+1]=DP[i];
- S[i]<S[i]+1,DP[i+1]=DP[i]+1;
最后输出DP[S.length()]即可。