题目大意:
就是给你两摞扑克牌,每摞有C张(100),洗牌操作就是完美的洗牌操作,一张插一张,然后就得到的牌再分成两摞,继续之前的操作,问你是否有可能洗出他所给出的目标顺序。1000组测试数据。 

首先需要证明一个事情,就是,这两摞牌一直进行完美洗牌操作,进行若干次之后就会得到和原来一样的两摞牌。而且这个次数,只由牌数n确定。(在这里我默认的是所有牌都是不一样的)。
举例感觉一下:
5678 1234-->1526 3748-->3175 4286-->4321 8765这个疗程使两摞交换顺序并且两摞的牌都倒置,再继续一个疗程就变回原样了。这里发现,对于一个数的变化,对于数5,他的位置的变化是1-2-4-8-7-5-1。

那么,显然,显然,显然,对于一个第i次完美洗牌之后位于a[i]的数,一次完美洗牌之后,它的位置变化规律如下:


a[i+1]=( a[i]<=n/2 ? 2*a[i] : (a[i]-n/2)-1);

对于每摞有n张的两摞牌,变回与原来的样子所需要的完美洗牌次数为:我不会用n表示。


思路:

最简单的方法就是一直模拟,对于起始序列一直进行完美洗牌操作,直到再一次变为起始序列,每次操作之后,都检查是否出现目标序列。时间复杂度分析:1000组测试实例,每次洗牌操作需要100+判断需要200,洗牌操作最多可能进行多少次我不知道,设为s次。1000*300*s=3s*10e5。我赌一下,洗牌次数不会超过1000次。 

#include<iostream>
#include<math.h>
#include<string.h>
#include<stdio.h>
using namespace std;

int s[210]={0};
int e[210]={0};
int n;
int sum=0;

bool same(int a[],int b[])
{
	int i=1;
	while(a[i]!=0)
	{
		if(a[i]!=b[i])return 0;
		i++;
	}
	return 1;
}
void ceshi(int a[])
{
	for(int i=1;i<=2*n;i++)
	{
		cout<<a[i];
	}
	cout<<endl;
}
void dfs(int a[])
{
	//ceshi(a);
	if(same(a,e)==1)
	{
		return;
	}
	sum++;
	int next[210]={0};
	for(int i=1;i<=n;i++)
	{
		next[2*i]=a[i];
	}
	for(int i=n+1;i<=2*n;i++)
	{
		next[2*i-2*n-1]=a[i];
	}
	//ceshi(next);
	if(same(next,s)==1)
	{
		sum=-1;
		return;
	}
	dfs(next);
}

int main()
{
	int test;
	cin>>test;
	for(int k=1;k<=test;k++)
	{
		sum=0;
		cin>>n;
		getchar();
		char l;
		for(int i=2*n;i>=n+1;i--)
		{
			scanf("%c",&l);
			s[i]=(int)(l-'A')+1;
		}
		getchar();
		for(int i=n;i>=1;i--)
		{
			scanf("%c",&l);
			s[i]=(int)(l-'A')+1;
		}
		getchar();
		for(int i=2*n;i>=1;i--)
		{
			scanf("%c",&l);
			e[i]=(int)(l-'A')+1;
		}
		getchar();
		dfs(s);
		cout<<k<<" "<<sum<<endl;
		memset(s,0,sizeof(s));
		memset(e,0,sizeof(e));
	}
}


注意,给你的S1,S2里面每种牌的个数有可能与目标序列里该种牌的个数不一样。

分类被分为广搜,本来以为会有什么更快的方法,但是去网上查了一下题解发现大家都是这个思路做成的模拟,也许是有什么大神级方法我没想道吧。