Educational Codeforces Round 97 1437B Reverse Binary Strings

题目链接

在这里插入图片描述

题目翻译:

给你一个长度为n的字符串s,其中n是偶数,并且s是二进制串,即只由’0’和’1’组成。
s有n/2个’0’和n/2个’1’(n是偶数)。
在一次操作中,你可以翻转s的任意子串,一个字符串的子串指的是该字符串的一段连续的字符串。
你需要执行多少次这样的操作,使得字符串中的’0’和’1’是交替出现的,即对于所有的i,si≠si+1都成立。比如:01010101…和10101010…

解题思路:

在这里插入图片描述
通过看题目给出的例子可以发现,下划线上的第一个数字1是连续两个1中的第二个1,下划线上的最后一个数字0是连续两个0中的第一个0
在这里插入图片描述
是否可以这样理解,如果有连续的数字,就需要翻转子字符串。而显然下划线的最后一位必须和下划线的第一位不同,并且最后一位数字也是有连续的数字的,这样翻转才能做到一石二鸟,是翻转次数尽可能地少。
这样虽然讲得通,但是似乎略显麻烦。再观察观察,前三个连续的1,在进行一次翻转后,依旧有两个1是相邻的,那这两个1肯定又需要一次翻转,使之分离。是否可以这样理解,一段连续的数字,需要翻转的次数是其长度减去1的值?
并且因为字符串只由两种字符组成,所以可以只考虑1或者只考虑0。
总结一下就是,需要翻转的次数等于字符串中所有连续的1(或0)的长度减一的和。语言表达可能不太准确,具体看代码。
但是又发现第二个例子0110,如果只考虑0,结果是错的,但是只考虑1就是对的。既然这样就干脆0和1都分别单独考虑,取最大值。

代码:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
int main(){
    
    
//	freopen("1.txt","r",stdin);
	int t,n;
	string s;
	cin>>t;
	while(t--){
    
    
		cin>>n>>s;
		int sum=0,sum1=0,sum2=0,flag=0;
		for(int i=0;i<n;i++){
    
    
			if(s[i]=='0'){
    
    
				sum++;
			}else{
    
    
				if(sum){
    
    
					sum1+=sum-1;
				}
				sum=0;
			}
		}
		sum=0,flag=0;
		for(int i=0;i<n;i++){
    
    
			if(s[i]=='1'){
    
    
				sum++;
			}else{
    
    
				if(sum){
    
    
					sum2+=sum-1;
				}
				sum=0;
			}
		}
		cout<<max(sum1,sum2)<<endl;
	}
	return 0;
}
总结:

事实证明,多思考思考,是可以省下很多代码的。如果按最开始的思路,我可能要写好久好久。

猜你喜欢

转载自blog.csdn.net/lmmmmmmmmmmmmmmm/article/details/109330694
今日推荐