(水)POJ-3087 模拟,map,string

题目大意: 已知两堆牌 s1 s2 的初始状态,   其牌数均为 c ,按给定规则能将他们相互交叉组合成一堆牌 s12 ,再将 s12 的最底下的 c 块牌归为 s1 ,最顶的 c 块牌归为 s2 ,依此循环下去。

 

现在输入s1s2的初始状态 以及 预想的最终状态s12

s1 s2经过多少次洗牌之后,最终能达到状态s12,若永远不可能相同,则输出"-1"

题目链接:点击打开链接

分析:网上将这题放在了BFS里,可这里的变换是固定的,所以实在是想不出怎么BFS,,,由于每次操作都是给定的,所以就是个简单的模拟题。这里要注意到的一点就是判重(即永远也不能变成需要的牌堆),用map就可以轻松解决了。值得一提的是,如何正确使用map。请看代码注释。


附上代码:

#include<iostream>  //POJ-3087
#include<string>
#include<map>
using namespace std;
int N, n;
string s1, s2, s, ss;
map<string, int> vis;
int solve()
{
	int res = 0;
	while (1)
	{
		for (int i = 0; i < n; i++)       //s1+s2->s,合并
		{
			s[2 * i] = s2[i];
			s[2 * i + 1] = s1[i];
		}
		res++;
		if (s == ss) return res;		//如果达到就返回res
		if (vis[s]) return -1;			//在这里,可能刚接触STL的人就看不太懂了,在前面我们并没有执行vis[s]=1;将s这个键加入到vis中之类的
		vis[s] = 1;						//操作。这就是前面说到值得注意的一点,vis[s]这个操作会自动将s这个键加入,并将对应的键值默认为0。
		for (int i = 0; i < n; i++)   //s->s1+s2,拆分
		{
			s1[i] = s[i];
			s2[i] = s[i + n];
		}
	}
}
int main()
{
	scanf("%d", &N);
	int T = 0;
	while (T++ < N)
	{
		scanf("%d", &n);
		cin >> s1 >> s2 >> ss;
		s.resize(2 * n);			 //重定义s的大小,以便于在之后可以直接用取下标的方式赋值
		printf("%d %d\n", T, solve());
	}
	return 0;
}



你可能感兴趣的:(模拟,ACM,STL,题解报告)