1. 程式人生 > >ZOJ 4060 Flippy Sequence(思維)

ZOJ 4060 Flippy Sequence(思維)

題目連結:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4060

題目大意:有兩個只包含0和1字串,,通過將字串1區間內的0和1反轉2次(0反轉為1,1反轉為0),求方案數。

思路:反轉的順序不會影響最後的結果。為了方便分析,我將所有的字串2都看作是0組成的,字串1內的1就是需要我們反轉的,分析以下情況。

(1)字串全為1,例如:1,11,111,1111。其對應的方案數為,0,2,4,6.。ans=(n-1)*2;

(2)字串全為0,例如:0,00,000,0000。其對應的方案數為,1,3,6,10.。ans=(n+1)*n./2;

(3)0001100型別,l表示左邊0的個數,mid表示中間0的個數,r表示右邊0的個數。ans=(mid-1)*2+(l+r)*2;

(4)000110011000型別,恰好兩對連續的1,ans=6;

(5)000110011011,00110011011011011...型別,出現了3個及以上的連續的1,我們無法通過反轉2次得到答案,ans=0;

AC程式碼:

#include <cstdio>
#include <queue>
#include <iostream>
using namespace std;

const int MAXN = 1e6+10;
char str1[MAXN];
char str2[MAXN];
typedef long long ll;
int main(){
	//freopen("in.txt","r",stdin);
	int T;scanf("%d",&T);
	while(T--){
		int n;scanf("%d",&n);
		scanf("%s%s",str1,str2);
		int flag=0;
		int sameCnt=0,diffCnt=0;
		queue<int> aSame,aDiff;
		while(!aSame.empty()) aSame.pop();
		while(!aDiff.empty()) aDiff.pop();
		//flag=1表示正在計數連續相同的字串長度
		//flag=2表示正在計數連續不相同的字串長度
		for(int i=0;i<n;i++){
			if(str1[i]==str2[i]){
				if(flag==1){
					sameCnt++;
				}else if(flag==2){
					aDiff.push(diffCnt);
					diffCnt=0;
					sameCnt=1;
					flag=1;
				}else{
					sameCnt++;
					flag=1;
				}
			}else{
				if(flag==2){
					diffCnt++;
				}else if(flag==1){
					aSame.push(sameCnt);
					sameCnt=0;
					diffCnt=1;
					flag=2;
				}else{
					diffCnt++;
					flag=2;
				}
			}
		}
		if(sameCnt) aSame.push(sameCnt);
		if(diffCnt) aDiff.push(diffCnt);
		ll ans=0;
		if(aSame.size()==1&&aDiff.size()==0){
			ans=(n+1)*n/2;
			printf("%lld\n",ans);
			continue;
		}
		if(aDiff.size()>2){
			printf("0\n");
			continue;
		}
		bool firstSame=0;
		if(str1[0]==str2[0])
			firstSame=1;
	
		int l,r,mid;
		if(firstSame){
			if(aDiff.size()==1){
				l=0;r=0;mid=0;
				mid=aDiff.front();aDiff.pop();
				l=aSame.front();aSame.pop();
				if(aSame.empty())
					ans=(mid-1)*2+l*2;
				else{
					r=aSame.front();aSame.pop();
					ans=(mid-1)*2+(l+r)*2;
				}
			}else{
				ans=6;
			}
		}else{
			if(aDiff.size()==1){
				l=0;r=0;mid=0;
				l=aDiff.front();aDiff.pop();
				if(!aSame.empty()){
					mid=aSame.front();
					aSame.pop();
				}
				ans=(l-1)*2+mid*2;
			}else{
				ans=6;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}