Shuffle’m Up POJ - 3087
题目链接:https://vjudge.net/problem/POJ-3087
题意:(1)有两副颜色多样的扑克牌,(A~H)表示不同颜色,给你两副牌,S1,S2和一副你需要洗出的KEY,S12由S2最底部,S1底部。。。一直下去,直到洗成S12,就是图片展示的那样。
(2)洗好的S12可以重新变成新的S1,S2,S1是从下取S12牌数的一半,S2的从上取S12牌数的一半,
问:这样操作有限次,能不能洗出S3,可以的话,求出最少洗牌次数,不能的话输出-1.
思路:算一个水题吧,简单的模拟,就是按照洗牌,拆牌那样模拟就好了,为了确定这个KEY能不能洗出,需要一个map<string,bool>,标记每次洗出的牌S12的字符串,如果洗出了之前洗出过的牌S12,说明KEY无法被洗出。
#include <iostream>
#include <cstring>
#include<string>
#include <cmath>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;
#define inf (1LL << 31) - 1
#define rep(i,j,k) for(int i = (j); i <= (k); i++)
#define rep__(i,j,k) for(int i = (j); i < (k); i++)
#define per(i,j,k) for(int i = (j); i >= (k); i--)
#define per__(i,j,k) for(int i = (j); i > (k); i--)
int ans;
string a, b, key;
int len;
//洗牌函数
inline void Insert(string& tmp, string& a, string& b){
int l = 0;
rep__(i, 0, len){
tmp[l++] = b[i];
tmp[l++] = a[i];
}
}
bool bfs(){
map<string, bool> mp;
string tmp(2*len,'0');
ans = 0;//初始化洗牌次数
Insert(tmp, a, b);
while (!mp[tmp]){ //该S12没出现过
mp[tmp] = true; //标记新S12
++ans;
if (tmp == key) return true; //洗出了KEY
//把S12拆成S1和S2
rep__(i, 0, len) a[i] = tmp[i];
rep__(i, len, 2 * len) b[i - len] = tmp[i];
//重新洗牌
Insert(tmp, a, b);
}
//洗不出KEY
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
rep(i, 1, n){
cin >> len >> a >> b >> key;
cout << i << " ";
if (bfs()) cout << ans << endl;
else cout << "-1" << endl;
}
return 0;
}