num.7 Shuffle'm Up POJ - 3087

题意

输入一个N,表示有N组数据,每组数据有四行,第一行是一个整数C,表示 每堆牌的数量,接下来是三行字符序列,第一行是S1堆,第二行是S2堆,第三行S12是预想的排序序列,求需要几步才能到达预想序列。

已知两堆牌s1和s2的初始状态, 其牌数均为c,按给定规则能将他们相互交叉组合成一堆牌s12,再将s12的最底下的c块牌归为s1,最顶的c块牌归为s2,依此循环下去。现在输入s1和s2的初始状态 以及 预想的最终状态s12.问s1 s2经过多少次洗牌之后,最终能达到状态s12,若永远不可能相同,则输出"-1"。在这里插入图片描述

分析

洗牌。两摞牌数相同。每个字母代表一个颜色,给出两摞牌的顺序,最后一行为洗牌目标。

利用bfs搜索。每摞最后一个为s2的,最上面的是s1的,如果新的序列s与目标序列相同,返回洗牌次数,如果不相同,将序列s重新分成两摞,下半部分是s1的,上半部分是s2的。由此进行。
每次洗牌需进行查重。防止进入循环状态而无解。

#include<iostream>
#include<queue>
#include<cstdio>
#include<map> 
using namespace std;
int n,m,t;
string s1,s2,s;
struct node{
	int num;//计数 
	string s;
};
map<string,int>p;
int bfs(node a)
{
	queue<node>q;
	p.clear(); //删除所有元素 
	q.push(a);//从已有元素后增加元素 
	while(!q.empty()){//判断是否为空 
		node u=q.front();//把第一个元素给u 
		q.pop();//清除第一个元素 
		if(u.s==s&&u.num!=0)
		    return u.num;
		node v;
		int i;
		for(i=0;i<n;i++)//洗牌穿插 
		{
			v.s += u.s[n+i];
			v.s +=u.s[i];
		}
		if(!p.count(v.s)){//判断是否为目标顺序 
			p[v.s]=1;//标记。证明其不会有重复的顺序 
			v.num=u.num+1;
			q.push(v);
		}
	}
	return -1;
}
int main()
{
	int k=0;
	cin>>t;
	while(t--)
	{
		cin>>n>>s1>>s2>>s;
		node u;
		u.s=s1+s2;
		u.num=0; 
		int ans=bfs(u);
		printf("%d %d\n",++k,ans);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值