题目描述
OJ地址 http://lx.lanqiao.cn/problem.page?gpid=T447
小的时候,你玩过纸牌游戏吗?
有一种叫做“拉马车”的游戏,规则很简单,却很吸引小朋友。
其规则简述如下:
假设参加游戏的小朋友是A和B,游戏开始的时候,他们得到的随机的纸牌序列如下:
A方:[K, 8, X, K, A, 2, A, 9, 5, A]
B方:[2, 7, K, 5, J, 5, Q, 6, K, 4]
其中的X表示“10”,我们忽略了纸牌的花色。
从A方开始,A、B双方轮流出牌。
当轮到某一方出牌时,他从自己的纸牌队列的头部拿走一张,放到桌上,并且压在最上面一张纸牌上(如果有的话)。
此例中,游戏过程:
A出K,B出2,A出8,B出7,A出X,此时桌上的序列为:
K,2,8,7,X
当轮到B出牌时,他的牌K与桌上的纸牌序列中的K相同,则把包括K在内的以及两个K之间的纸牌都赢回来,放入自己牌的队尾。注意:为了操作方便,放入牌的顺序是与桌上的顺序相反的。
此时,A、B双方的手里牌为:
A方:[K, A, 2, A, 9, 5, A]
B方:[5, J, 5, Q, 6, K, 4, K, X, 7, 8, 2, K]
赢牌的一方继续出牌。也就是B接着出5,A出K,B出J,A出A,B出5,又赢牌了。
5,K,J,A,5
此时双方手里牌:
A方:[2, A, 9, 5, A]
B方:[Q, 6, K, 4, K, X, 7, 8, 2, K, 5, A, J, K, 5]
注意:更多的时候赢牌的一方并不能把桌上的牌都赢走,而是拿走相同牌点及其中间的部分。但无论如何,都是赢牌的一方继续出牌,有的时候刚一出牌又赢了,也是允许的。
当某一方出掉手里最后一张牌,但无法从桌面上赢取牌时,游戏立即结束。
对于本例的初始手牌情况下,最后A会输掉,而B最后的手里牌为:
9K2A62KAX58K57KJ5
本题的任务就是已知双方初始牌序,计算游戏结束时,赢的一方手里的牌序。当游戏无法结束时,输出-1。
输入:
输入为2行,2个串,分别表示A、B双方初始手里的牌序列。
输出:
输出为1行,1个串,表示A先出牌,最后赢的一方手里的牌序。
样例输入1:
96J5A898QA
6278A7Q973
样例输出1:
2J9A7QA6Q6889977
样例输入2:
25663K6X7448
J88A5KJXX45A
样例输出2:
6KAJ458KXAX885XJ645
思路:
考查的是栈和队列的用法,其实过程很简单,也很好理解,只要把过程模拟出来就可以了。大致流程:
手里的牌 用队列
出去的牌 用栈
每次出牌 遍历一下栈 判断能不能拿走下面的牌 如果拿走了,那就继续出牌 拿不走 就对方出牌
要注意的一点就是对局的结束条件,出完了最后一张牌以后,还要判断一下能不能在“打出去的牌中拿回来一些牌”,不能认为手里的牌空了就是对局结束了,忽略了这一点的话,6个测试点可以通过4个,有一个测试会用到这个判断。
代码1
#include <bits/stdc++.h>
using namespace std;
stack<char> s;
queue<char> a,b;
int main(){
string sc1,sc2;
cin >> sc1;
cin >> sc2;
for(int i = 0; i < sc1.size();i++){
a.push(sc1[i]);
b.push(sc2[i]);
}
// A开始出牌
s.push(a.front());
a.pop();
queue<char> *tmp_cur = &b; //现在该出牌的
queue<char> *tmp_just = &a; // 刚才出过牌的
while(true){
// 刚出过牌 先判断一下能不能拿 检查的是刚才出牌的人,即tmp_just这个,可以的话,tmp_just继续出牌
char just_card = s.top();
s.pop(); // 先弹出去 下边好判断
bool f = false; // 拿没拿走的标志
string str_card = "";
/* 用于暂时存放从栈中遍历时 拿出去的那些牌,如果能拿走下面的牌,就把这个string里的char逐个push到刚才出牌人的手中
如果不能,那就把这些char放回栈中
*/
str_card += just_card;
if(s.empty()){ //没牌了
// 下面没牌直接放 不检查
s.push(just_card);
}else{
// 开始检查是否出过这牌 ;
while(!s.empty()){
if( just_card != s.top() ){
str_card += s.top(); // 后拿出来的牌 往后放 入栈倒着来 给出牌人的话 正着给
s.pop();
}else{
// 可以拿走
f = true;
str_card += s.top();
s.pop(); //先拿出来
for(int i = 0; i < str_card.size(); i++){
tmp_just->push(str_card[i]); //给刚才的出牌人
}
}
if(f){
break;
}
}
// 检查结束
if(!f){ // 没拿走 得把牌放回栈里
// cout << "历史出牌:" << str_card << "所以拿不走" << endl;
for(int i = str_card.size()-1; i>=0 ; i--){
s.push(str_card[i]);
}
}
}
if(f){ //拿走了 再出一张
s.push(tmp_just->front());
tmp_just->pop();
}else if(a.empty() || b.empty()){
break; //对局结束 手中没牌了,上一次出完就没了,并且在上边判断的时候,他出的最后一张牌也不能“拿回下面的牌”。
}else{ // 对方出一张
s.push(tmp_cur->front());
tmp_cur->pop();
// 交换出牌的两个人
queue<char> *temp = tmp_just;
tmp_just = tmp_cur;
tmp_cur = temp;
}
// 进行下一次出牌
}
if(!a.empty()){ //A赢
//cout << "A 赢了" << endl;
while(!a.empty()){
cout << a.front();
a.pop();
}
}else{
// cout << "B 赢了" << endl;
while(!b.empty()){
cout << b.front();
b.pop();
}
}
return 0;
}