有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌。但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作。
Input
有多个case,每个case输入一行01符号串(长度不超过20),1表示反面朝上,0表示正面朝上。
Output
对于每组case,如果可以翻,输出最少需要翻动的次数,否则输出NO。
Sample Input
01
011
Sample Output
NO
1
本题主要是需要考虑两边翻动的话可以只翻动两张牌,而中间的翻动却要翻动三次,可以将其当作两种情况来考虑,一种是左边不翻动,直接从第二个开始翻动,然后翻动相邻两个(相当于从第一个开始连续翻动三个),一直翻动到倒数第二个即可,而另一种情况就是先翻动前面两个,再按照刚刚那样翻动即可。
#include<bits/stdc++.h>
using namespace std;
int main(){string s;int book[100], sign[100];while(cin>>s){memset(book,0,sizeof(book));memset(sign,0,sizeof(sign));for(int i=0; i<s.length(); i++){book[i] = s[i]-'0';sign[i] = s[i]-'0';if(book[i]==0){ //将0用-1来表示,待会方便翻转book[i] = -1;sign[i] = -1;}}book[0] = -book[0], book[1] = -book[1];//考虑到先翻前两个的时候int sum = 1;//翻动次数要加1for(int i=0; i<s.length()-1; i++){//从第一个开始连续翻三个if(book[i]==1){book[i] = -book[i];book[i+1] = -book[i+1];book[i+2] = -book[i+2];sum++;}}int flat=0;if(book[s.length()-1]==1){//判断是否反转成功flat=1;}int sum2=0;//不考虑翻转前两个的情况for(int i=0; i<s.length()-1; i++){if(sign[i]==1){sign[i] = -sign[i];sign[i+1] = -sign[i+1];sign[i+2] = -sign[i+2];sum2++;}}int glat=0;//判断是否反转成功if(sign[s.length()-1]==1){glat=1;}if(flat&&glat){//如果2种情况都不成功输出Nocout<<"NO"<<endl; }else{if(flat==0&&glat==0)//两种情况都符合就找最小的那个,否则哪个成功输出哪个cout<<min(sum,sum2)<<endl;else if(flat==0)cout<<sum<<endl;else cout<<sum2<<endl;}}
}