题目链接:http://codeforces.com/contest/604/problem/C
大致题意:给定一个01串以及其长度,求此串中符合形如“0101“或”101“这种01交错的序列(不必连续)的长度,并且你可以选定这个串中1段连续的子串进行反转(将0反转为1,将1反转为0),力求反转之后的串中所符合题意的序列的长度最大,并输出其长度。
(题目中”he decides that he will flip exactly one substring—that is, take a contiguous non-empty substring of his score and change all '0's in that substring to '1's and vice versa.“ 中的 ”vice versa“的意思是”反之亦然“,英语不好没读懂,以为只能将0反转为1,WA了好几次,哭瞎)
大致思路:
串中如果有一处00或11这样连个在一起的,我们可以改变之前或者之后的所有数,则序列长度可以增加1。形如:1101,序列长度为3,反转成1[010],序列长度为4.
如果有两处,则我们可以改变这两处之间所有的数,序列长度可以增加2。形如: 110100,原本序列长度为4,然后反转成1[0101]0,反转之后的序列长度为6.
遇见000 111这样的三个连在一起的,则可以将形如”000“改为”010“,可以直接判断序列增加2
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 6 using namespace std; 7 8 string arr; //存储01串 9 int main() 10 { 11 int n; 12 cin>>n; 13 cin>>arr; 14 int countr=1; //记录符合题意的序列的长度 15 int mark=0; //记录反转可以增加的长度 16 17 char tmp=arr[0]; 18 for( int i=1; i<n; i++ ) 19 { 20 if( arr[i]!=tmp ) 21 { 22 countr++; 23 tmp=arr[i]; 24 } 25 } 26 27 for( int i=0; i<n; i++ ) 28 { 29 int flag=1; 30 for( int j=i; j+1<n && arr[j]==arr[j+1]; j++ ) 31 flag++; 32 if( flag>2 ) //串中有三个以上连续的1或0,直接认定序列长度可以加2 33 { 34 mark=2; 35 break; 36 } 37 if( flag==2 && mark==0 ) //串中有一出连续的两个1或0 38 { 39 mark=1; 40 i++; 41 } 42 //注意第三个if要加else if,第二个if的执行体中改变了第三个if的判断条件,会导致第二个if执行完后第三个接着就执行了 43 else if( flag==2 && mark==1 ) //串中有两处连续的1或0,直接认定序列长度可以加2 44 { 45 mark=2; 46 break; 47 } 48 } 49 countr+=mark; 50 printf( "%d ",countr ); 51 return 0; 52 }
其实直接一层循环就可以搞定:遇见arr[i-1]==arr[i]的情况就mark++,mark加到2就break掉。我这么写加了很多逻辑判断,很丑了。
又PS:几个if一起用的时候一定要注意其其中的逻辑,特别注意“上面if执行完后直接正好满足了下一个if的条件”的情况