SOJ 1018

1018. A Card Trick

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge

Description

The following card trick is performed by a Magician and her Assistant. The Assistant asks a member of the audience to choose 5 cards from a standard deck of 52 cards (A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K of C[lubs], D[iamonds], H[earts] and S[pades]). The Assistant returns one of the cards to the audience member and then hands the remaining cards to the Magician, one at a time. After suitable mumbo-jumbo, the Magician identifies the (fifth) card held by the audience member.   

The Magician determines the card as follows:   

The order of the cards in the deck is determined first by the value and for cards of the same value by the suit (both in the order given above). So the total order of cards is: AC, AD, AH, AS, 2D, … , KH, KS   

  1. Remember the suit and value of the first card.  
  2. Among the remaining three cards find the position of the smallest card (in the above order). Add this position (1, 2, or 3) to the value of the first card.  
  3. If the larger two of the last three cards are not in order, add 3 to the result of step 2.  
  4. The missing card has the same suit as the first card and value that computed in step 3 wrapping around if necessary.    

For example:   

QH, 10D, 10C, 4D   

Smallest of the last 3 cards is 4D in place 3. 10D and 10C are out of order so add 3 + 3 to Q. Wrapping around the missing card is 5H.  

This problem is to write a program to perform the function of the Assistant.

Input

The first line of the input file named j.in consists of a positive integer n, which is the number of datasets that follow. Each of the n following lines contain one data set. The dataset is a sequence of 5 cards separated by a space. Each card is given by a one or two character value and a one character suit as described in the first paragraph.

Output

For each dataset, the output on separate lines is an ordering of the 5 input cards as shown in the sample output. The first card in the sequence is the card to be returned to the audience member. The remaining cards are those given to the Magician (in the order given to the Magician). There may be more than one solution to some problems (but that is not to say there *will* be). In cases such as these, any of the correct solutions will be accepted by the judges. For instance 10D 4D QH 10C 5H is also a solution to the first problem below.

Sample Input

2						4D 5H 10C 10D QH			7H 5C KS 6C 8D 

Sample Output

Problem 1: 5H QH 10D 10C 4DProblem 2: 6C 5C 7H 8D KS


  给定五张牌,要找出适当的排列方式使之满足题目要求。首先第一张牌和第二张牌花色必须相同,然后第二张牌数字加上x对13取余要等于第一张牌的数字,依据题意x可以为1,2,3,4,5,6,即第二张牌减去第一张牌等于-6,-5,-4,-3,-2,-1或者7,8,9,10,11,12,所以只需要对前两张牌进行排列组合(共20种情况),当满足花色相同且第二张减去第一张等于前面列出的12个数字之一。具体详见代码注释。

// Problem#: 1018
// Submission#: 5045419
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<iterator>
using namespace std;
struct card{//牌类型,数据成员包括牌的数字,花色,以及是否被访问过 
    int number;
    char suit;
    int visited;
    card(){
    }
    card(int num,char s,int v)
    {
        number=num;
        suit=s;
        visited=v;
    }
    bool operator==(card A)//重载等于号 
    {
        return this->number==A.number&&this->suit==A.suit;
    }
}; 

int flag;//用来记录是否找到可行解 
vector<card> initial;//保存这五张牌的初始顺序,即输入顺序 
vector<card> final;//保存最终顺序,即满足条件的顺序 
int n;//case个数 

int toNumber(char c)//将牌的大小转换成int类型 
{
    if(c=='A') return 1;
    else if(c>='2'&&c<='9')  return c-'0';
    else if(c=='J') return 11;
    else if(c=='Q') return 12;
    else return 13; 
}

char toCharacter(int i)//将int类型再转换成表示牌的大小的符号 
{
    if(i==1) return 'A';
    else if(i>=2&i<=9) return i+'0';
    else if(i==11) return 'J';
    else if(i==12) return 'Q';
    else return 'K';
}
bool cmp(card A,card B)//比较函数,当A小于B时返回真 
{
    if(A.number!=B.number) return A.number<B.number;
    else return A.suit<B.suit;
}

void findAnswer()
{
    initial.clear();//清空两个容器 
    final.clear();
    flag=0;//重置为未找到可行解 
    string s;
    int gap;
    for(int i=0;i<5;++i)
    {
        cin>>s;//接受五个字符串,即五张牌 
        if(s.length()==3) initial.push_back(card(10,s[2],0));//若字符串的长度为3则必定牌的大小是10 
        else initial.push_back(card(toNumber(s[0]),s[1],0));
    }
    for(vector<card>::iterator iter=initial.begin();iter!=initial.end();++iter)//遍历前两张牌可行的组合寻找可行解 
    {
        final.push_back(*iter);
        iter->visited=1;
        for(vector<card>::iterator iter1=initial.begin();iter1!=initial.end();++iter1)
        {
            gap=iter1->number-iter->number;//gap存储前两张牌之差 
            if(!iter1->visited&&iter->suit==iter1->suit&&((gap>-7&&gap<0)||(gap>6&&gap<13)))//满足条件则找到一个可行解 
            {
                flag=1;
                final.push_back(*iter1);
                initial.erase(iter1);//前两张牌已经按照顺序存入final容器中,为了确定剩下的三张牌,所以将已经存入final的牌在initial中删除掉,此条语句删除了一张 
                break;
            }
        }
        if(flag) 
        {
            initial.erase(find(initial.begin(),initial.end(),final[0]));//由于用erase删除了iter1指向的牌后iter迭代器可能失效,所以不直接erase(iter),用find语句先确定要删除牌的位置再用erase删除 
            break;
        }
        else
        {
            final.pop_back();
            iter->visited=0;
        }
    }
    sort(initial.begin(),initial.end(),cmp);//此时initial中还剩三张牌,将其排序确定最小牌,中间牌和最大牌 
    card min=initial[0];
    card mid=initial[1];
    card max=initial[2];
    if(gap==-6||gap==7)//根据gap具体的值确定最后三张牌的顺序 
    {
        final.push_back(max);
        final.push_back(mid);
        final.push_back(min);
    }
    else if(gap==-5||gap==8)
    {
        final.push_back(max);
        final.push_back(min);
        final.push_back(mid);
    }
    else if(gap==-4||gap==9)
    {
        final.push_back(min);
        final.push_back(max);
        final.push_back(mid);
    }
    else if(gap==-3||gap==10)
    {
        final.push_back(mid);
        final.push_back(max);
        final.push_back(min);
    }
    else if(gap==-2||gap==11)
    {
        final.push_back(mid);
        final.push_back(min);
        final.push_back(max);
    }
    else if(gap==-1||gap==12)
    {
        final.push_back(min);
        final.push_back(mid);
        final.push_back(max);
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;++i)
    {
        findAnswer();
        cout<<"Problem "<<i+1<<":";
        for(int j=0;j<5;++j)
        {
            if(final[j].number==10) cout<<" "<<"10"<<final[j].suit;
            else cout<<" "<<toCharacter(final[j].number)<<final[j].suit;
        }
        cout<<endl;
    }
    return 0;
}                                 

的时候即找到一种可能,然后再根据具体的具体的两牌之差就可以确定后三张牌的顺序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值