SOJ 1003

1003. Hit or Miss

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

One very simple type of solitaire game known as "Hit or Miss" (also known as "Frustration," "Harvest," "Roll-Call," "Talkative", and "Treize") is played as follows: take a standard deck of 52 playing cards four sets of cards numbered 1 through 13 (suits do not matter in this game) which have been shuffled and start counting through the deck 1, 2, 3, . . . , and so on. When your count reaches 13, start over at 1. Each time you count, look at the top card of the deck and do one of two things: if the number you count matches the value of the top card, discard it from the deck; if it does not match it, move that card to the bottom of the deck. You win the game if you are able to remove all cards from the deck (which may take a very long time). A version of this game can be devised for two or more players. The first player starts as before with a 52 card deck, while the other players have no cards initially. As the first player removes cards from her deck, she gives them to the second player, who then starts playing the same game, starting at count 1. When that player gets a match, he passes his card to the third player, and so on. The last player discards matches rather than passing them to player 1. All players who have cards to play with perform the following 2-step cycle of moves in lockstep: 1. Each player says his or her current count value and checks for a match. If there is no match, the top card is moved to the bottom of the deck; otherwise it is passed to the next player (or discarded if this is the last player). 2. Each player except the first takes a passed card (if there is one) and places it at the bottom of his or her deck. These rules are repeated over and over until either the game is won (all the cards are discarded by the last player) or an unwinnable position is reached. If any player ever runs out of cards, he waits until he is passed a card and resumes his count from where he left off. (e.g., if player 3 passes his last card on a count of 7, he waits until he receives a card from player 2 and resumes his count with 8 at the beginning of the next 2-step cycle).

Input

Input will consist of multiple input sets. The first line of the file will contain a single positive integer nindicating the number of input sets in the file. Each input set will be a single line containing 53 integers: the first integer will indicate the number of players in the game and the remaining 52 values will be the initial layout of the cards in the deck, topmost card first. These values will all lie in the range 1 . . . 13, and the number of players will lie in the range 1. . . 10.

Output

For each input set, output the input set number (as shown below, starting with 1) and either the phrase "unwinnable" or a list showing the last card discarded by each player. Use a single blank to separate all outputs.

Sample Input

2
4 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13
4 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1

Sample Output

Case 1: 13 13 13 13
Case 2: unwinnable


   这题思路比较简单,按照说明可以用队列来模拟,每个人即为一个队列,用一个队列数组来保存所有人的牌。然后按照游戏的规则用循环对游戏过程进行模拟就行了。有一点要注意的是游戏的意思是每人对手上的牌进行一次判断,无论是否要传牌,之后都是下一人进行(如果下一任手上有牌的话,无牌则跳过),最后一人判断完之后第一人再进行判断,以此类推。我刚开始做的时候以为是第一人先进行多次判断,当第一人所有牌都传给第二人后第二人再进行判断,这样不仅超时而且结果也是错的。

  最后说明一下关于游戏无法完成的判断条件repnum,我本以为当repnum等于52时就可以认为整个传牌陷入了死循环,但只有当一个人有52张牌,且连续进行52次判断都没有将牌传个下一个人时,这个人手上的牌才陷入死循环,若当牌小于52时,就有可能需要大于52次判断才能向后传出一张牌,所以讲repnum上限设为52是错误的,具体上限的最小值应为多少貌似也比较难算,所以干脆设为52*52这个比较大的数,在实际测试中当上限为100就可以AC了。


// Problem#: 1003
// Submission#: 4919142
// 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<queue>
using namespace std; 

int repnum;//用来记录没有一个人把牌往下一个人传的最大连续次数 

inline void trans(queue<int>*q,int people,int lastcard[],int peoplevalue[])//q是队列数组,people保存游戏人数,lastcard数组记录每个人最后传出的一张牌,peoplevalue数组记录每个人当前数到的数 
{
    repnum++;//没进行一次传牌则repnum增加1 
    for(int i=0;i<people;++i)
    {
        if(q[i].empty())//若某人手中无牌则跳过他 
        continue;
        int front=q[i].front();
        q[i].pop();
        if(peoplevalue[i]==front)
        {
            lastcard[i]=front; 
            q[i+1].push(front);
            repnum=0;//当某人成功将牌传给下一个人,则一直没人往下一人传牌的情况被打破,连续次数归零,重新计数 
        }
        else
        {
            q[i].push(front);
        }
        peoplevalue[i]++;
        if(peoplevalue[i]==14)
        peoplevalue[i]=1; 
    }
}

int main()
{
    int n;
    cin>>n;
    int count=0;
    int lastcard[10];
    while(count<n)
    {
        repnum=0;
        int flag=0;//用来标记是否能完成整个游戏 ,若能完成则置为1 
        int people;
        cin>>people;
        int peoplevalue[10]={1,1,1,1,1,1,1,1,1,1};//每个人都是从1数到13,所有将数组全初始化为1 
        queue<int> q[11];//按题意最后一人应该将牌直接抛弃,但若有10个人,第10人将牌抛弃可以等价为传给第11个人,因为人数上限为10,所以将队列数组容量设为11 
        int x;
        for(int i=0;i<52;++i)
        {
            cin>>x;
            q[0].push(x);
        }
        while(repnum<52*52)//若repnum累计到一定大小则可以判定所有人手上的牌都进入了死循环,具体上限为多少我没有进行精确计算,但大于100就可以AC了 
        {
            trans(q,people,lastcard,peoplevalue);
            if(q[people].size()==52)//人数一共有people个,所以最后一人在数组的下标为(people-1),因为我们假定最后一人仍然再往后传,所以最后一人把牌抛弃完等价于下标为people的队列size为52 
            {
                flag=1;
                break;
            }
        }
        if(flag)
        {
            cout<<"Case "<<count+1<< ": ";
            for(int i=0;i<people-1;++i)
            cout<<lastcard[i]<<" ";
            cout<<lastcard[people-1]<<endl;
        }
        else cout<<"Case "<<count+1<<": "<<"unwinnable"<<endl;
        count++;
    }
    return 0;
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值