第八十九题 UVa246 10-20-30

116 篇文章 1 订阅

A simple solitaire card game called 10-20-30 uses a standard deck of 52 playing cards in which suit is
irrelevant. The value of a face card (king, queen, jack) is 10. The value of an ace is one. The value of
each of the other cards is the face value of the card (2, 3, 4, etc.). Cards are dealt from the top of the
deck. You begin by dealing out seven cards, left to right forming seven piles. After playing a card on
the rightmost pile, the next pile upon which you play a card is the leftmost pile.
For each card placed on a pile, check that pile to see if one of the following three card combinations
totals 10, 20, or 30.

  1. the first two and last one,
  2. the first one and the last two, or
  3. the last three cards.
    If so, pick up the three cards and place them on the bottom of the deck. For this problem, always
    check the pile in the order just described. Collect the cards in the order they appear on the pile and
    put them at the bottom of the deck. Picking up three cards may expose three more cards that can be
    picked up. If so, pick them up. Continue until no more sets of three can be picked up from the pile.
    For example, suppose a pile contains 5 9 7 3 where the 5 is at the first card of the pile, and then a
    6 is played. The first two cards plus the last card (5 + 9 + 6) sum to 20. The new contents of the pile
    after picking up those three cards becomes 7 3. Also, the bottommost card in the deck is now the 6,
    the card above it is the 9, and the one above the 9 is the 5.
    在这里插入图片描述
    If a pile contains only three cards when the three sum to 10, 20, or 30, then the pile ”disappears”
    when the cards are picked up. That is, subsequent play skips over the position that the now-empty
    pile occupied. You win if all the piles disappear. You lose if you are unable to deal a card. It is also
    possible to have a draw if neither of the previous two conditions ever occurs.
    Write a program that will play games of 10-20-30 given initial card decks as input.
    Input
    Each input set consists of a sequence of 52 integers separated by spaces and/or ends of line. The
    integers represent card values of the initial deck for that game. The first integer is the top card of the
    deck. Input is terminated by a single zero (0) following the last deck.
    Output
    For each input set, print whether the result of the game is a win, loss, or a draw, and print the number
    of times a card is dealt before the game results can be determined. (A draw occurs as soon as the state
    of the game is repeated.) Use the format shown in the “Sample Output” section.
    Sample Input
    2 6 5 10 10 4 10 10 10 4 5 10 4 5 10 9 7 6 1 7 6 9 5 3 10 10 4 10 9 2 1
    10 1 10 10 10 3 10 9 8 10 8 7 1 2 8 6 7 3 3 8 2
    4 3 2 10 8 10 6 8 9 5 8 10 5 3 5 4 6 9 9 1 7 6 3 5 10 10 8 10 9 10 10 7
    2 6 10 10 4 10 1 3 10 1 1 10 2 2 10 4 10 7 7 10
    10 5 4 3 5 7 10 8 2 3 9 10 8 4 5 1 7 6 7 2 6 9 10 2 3 10 3 4 4 9 10 1 1
    10 5 10 10 1 8 10 7 8 10 6 10 10 10 9 6 2 10 10
    0
    Sample Output
    Win : 66
    Loss: 82
    Draw: 73

【分析】
本题不算很难,但是十分考验代码能力,幸亏C++的强大能力,要不然就难搞了,Set deque vector的强大能力
写的时候注意 三张牌再次加入总堆的顺序

//
// Created by DELL on 2020/2/13.
//

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <set>
#include <queue>

using namespace std;
int num,zero[8];
vector<deque<int> > pip;// vector里面插七个双端队列
set<vector<deque<int> > > vis;
void init() {
    vis.clear();
    pip.clear();
    memset(zero,0,sizeof(zero));
    for(int i=0; i<8; i++) pip.push_back(deque<int> ());
    pip[7].push_back(num);
    for(int i=1; i<=51; i++) {
        scanf("%d",&num);
        pip[7].push_back(num);
    }
    for(int i=0; i<7; i++) {
        pip[i].push_back(pip[7].front());
        pip[7].pop_front();
    }
}

inline bool Judge(int x) {
    return (x == 10 || x == 20 || x == 30);
}

inline bool Suba(int point) {//头两张 和 末尾一张
    int bac = pip[point].front();
    pip[point].pop_front();
    int sum = bac + pip[point].front() + pip[point].back();
    if(Judge(sum)) {
        pip[7].push_back(bac);
        pip[7].push_back(pip[point].front());
        pip[7].push_back(pip[point].back());
        pip[point].pop_front();
        pip[point].pop_back();
        return true;
    }
    pip[point].push_front(bac);
    return false;
}

inline bool Subb(int point) {//头一张 和 末尾两张
    int bac = pip[point].back();
    pip[point].pop_back();
    int sum = bac + pip[point].front() + pip[point].back();
    if(Judge(sum)) {
        pip[7].push_back(pip[point].front());
        pip[7].push_back(pip[point].back());
        pip[7].push_back(bac);
        pip[point].pop_front();
        pip[point].pop_back();
        return true;
    }
    pip[point].push_back(bac);
    return false;
}

inline bool Subc(int point) {// 末尾三张
    int bac = pip[point].back();
    pip[point].pop_back();
    int bac1 = pip[point].back();
    pip[point].pop_back();
    int sum = bac + bac1 + pip[point].back();
    if(Judge(sum)) {
        pip[7].push_back(pip[point].back());
        pip[7].push_back(bac1);
        pip[7].push_back(bac);
        pip[point].pop_back();
        return true;
    }
    pip[point].push_back(bac1);
    pip[point].push_back(bac);
    return false;
}

inline bool Eliminate (int point){
    if(pip[point].size() < 3 ) return false;
    if(Suba(point)) return true;
    if(Subb(point)) return true;
    if(Subc(point)) return true;
    return false;
};

void solve() {
    int point = 0;
    for(int t=8; ; t++) {
        pip[point].push_back(pip[7].front());
        pip[7].pop_front();
        while(Eliminate(point)) ;
        if(pip[point].size() == 0) zero[point] = 1;
        point = (point + 1) % 7;
        if(pip[7].size() == 52) { printf("Win : %d\n",t); return ; }// 七堆全消除 那么总堆就有52张牌
        if(pip[7].size() == 0) { printf("Loss: %d\n",t); return; }
        if(vis.count(pip)) { printf("Draw: %d\n",t); return ; }
        vis.insert(pip);
        while(zero[point]) point = (point + 1) % 7;
    }
}

int main(int argc,char* argv[]) {
    while(scanf("%d",&num) == 1 && num) {
        init();
        solve();
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值