POJ 3087 Shuffle'm Up
题意:已知两队牌,数目都为C,序列为S1,S2。然后将S2最底部的一张牌作为牌数为2*C的新序列S12的底,接着交叉取S1,S2的牌叠到S12上。将S12下半部分C张牌作为新的S1,将S12上半部分C张牌作为新的S2。给定s1和s2的初始状态及要达到的最终状态s12,问s1 s2经过多少次上述洗牌之后,最终能达到状态s12,若永远不可能相同则输出-1。
分析:直接模拟操作即可。若s1和s2洗牌后的状态,是前面洗牌时已经出现过的一个状态,且这个状态不是要达到的状态S12,就说明已经陷入循环中不可能达到S12了。
代码1:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <queue> 6 #include <cmath> 7 #include <stack> 8 #include <set> 9 #include <map> 10 #include <algorithm> 11 using namespace std; 12 #define ll long long 13 #define inf 0x3f3f3f3f 14 string s1, s2, ss, str; 15 int main() 16 { 17 set<string> s;//将所有可能出现的序列都加入集合中判重 18 int T; 19 scanf("%d",&T); 20 for(int j=1; j<=T; j++) 21 { 22 int m;//牌数 23 scanf("%d", &m); 24 cin>>s1>>s2>>ss; 25 int cnt = 0; 26 s.clear(); 27 str = ss;//m=0为空串时的特殊情况 28 while (1) 29 { 30 int ind = 0; 31 for (int i=0; i<m; i++) 32 { 33 str[ind++] = s2[i]; 34 str[ind++] = s1[i]; 35 } 36 cnt++; 37 if(str == ss) 38 { 39 printf("%d %d\n", j, cnt); 40 break; 41 } 42 if(s.count(str) == 1) 43 { 44 printf("%d -1\n", j); 45 break; 46 } 47 else 48 { 49 s.insert(str);//新序列加入集合 50 s1.assign(str,0,m); 51 s2.assign(str,m,m); 52 } 53 } 54 } 55 return 0; 56 }
代码2:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <queue> 6 #include <cmath> 7 #include <stack> 8 #include <set> 9 #include <map> 10 #include <algorithm> 11 using namespace std; 12 #define ll long long 13 #define inf 0x3f3f3f3f 14 char a[105],b[105],d[205],w[205]; 15 int main() 16 { 17 int i,j,k,t,c,s; 18 scanf("%d",&t); 19 for(k=1;k<=t;k++) 20 { 21 scanf("%d",&c); 22 cin>>a>>b>>d; 23 map <string,bool> f;//map判重 24 f[d]=1; 25 s=0; 26 while(1) 27 { 28 for(i=0,j=0;i<c;i++) 29 { 30 w[j++]=b[i]; 31 w[j++]=a[i]; 32 } 33 w[j]='\0';//一定要构成串 34 s++; 35 if(strcmp(w,d)==0) 36 { 37 printf("%d %d\n",k,s); 38 break; 39 } 40 if(f[w]) 41 { 42 printf("%d -1\n",k); 43 break; 44 } 45 f[w]=1; 46 for(i=0;i<c;i++) 47 { 48 a[i]=w[i]; 49 b[i]=w[i+c]; 50 } 51 } 52 } 53 return 0; 54 }