UVaOJ 131 – The Psychic Poker Player


——by A Code Rabbit


Description

一道蛋疼的题目,堪称模拟题。

玩牌。

你有5张手牌,可以舍弃任意张,然后从桌上抽牌。

这时候,你突然牛逼了,你可以洞察桌上从上到下放的都是什么牌。

好了。

输入你手上的5张牌和桌面最上方的5张牌。

输出你可以拿到的最强的组合。


Types

Brute Force :: Elementary Skills


Analysis

要想A题,还要会玩扑克。


题目的样例已经给出扑克的各种组合的名称,并且从上到下,从强到弱。

这里也大概蛋疼得说明一下——

  • straight-flush,5张牌花色相同,点数递增1。
  • four-of-a-kind,5张牌有4张牌点数相同。
  • full-house,5张牌有3张牌点数相同,而且另外2张点数也相同。
  • flush,5张牌花色相同,但是点数没有递增1。
  • straight,5张牌点数递增1,但是花色不同。
  • three-of-a-kind,5张牌有3张点数相同,另外2张点数不同。
  • two-pairs,5张牌有两对牌点数相同。
  • one-pair,5张牌有一对牌点数相同。
  • highest-card,木有符合上面任何条件。


好了,接下来就是枚举弃牌的各种情况,然后各种蛋疼的判断函数,去判断牌属于什么类型。

枚举的时候,可以利用二进制数位运算。例如,

01010

就表示保留第二张和第四张牌,然后从桌上抽3张牌补齐5张。

而判断的时候,可以利用计数的思想——

  • 用一个count数组,计算点数出现的次数。
  • 再用另一个count数组,计算“点数出现次数”出现的次数……(虽然很绕口,但是你懂的)

这样就方便多了。


Solution

// UVaOJ 131
// The Psychic Poker Player
// by A Code Rabbit

#include <cstdio>
#include <cstring>
#include <map>

using namespace std;

struct Poker {
    char value;
    char suit;
};

const int NUM_CARD = 5;
const int LIMITS_VALUES = 15;

const char str_write[][20] = {
    "highest-card",
    "one-pair",
    "two-pairs",
    "three-of-a-kind",
    "straight",
    "flush",
    "full-house",
    "four-of-a-kind",
    "straight-flush",
};

enum Type {
    HIGHEST_CARD,
    ONE_PAIR,
    TWO_PAIRS,
    THREE_OF_A_KIND,
    STRAIGHT,
    FLUSH,
    FULL_HOUSE,
    FOUR_OF_A_KIND,
    STRAIGHT_FLUSH,
};

char ch;

map<char, int> int_value;

Poker hand[NUM_CARD];
Poker deck[NUM_CARD];
Type type_max;

int count_value[LIMITS_VALUES];
int count_value_same[NUM_CARD];

bool IsSameSuit(Poker card[]);
bool IsOrder(Poker card[]);
Type JudgeType(Poker card[]);

void Search(int x);

int main() {
    // Make map.
    int_value['A'] = 1;
    for (int i = 2; i < 10; ++i) {
        int_value['0' + i] = i;
    }
    int_value['T'] = 10;
    int_value['J'] = 11;
    int_value['Q'] = 12;
    int_value['K'] = 13;

    // Let's start the game!
    while (scanf("%c%c%c", &hand[0].value, &hand[0].suit, &ch) != EOF) {
        // Inputs.
        for (int i = 1; i < NUM_CARD; ++i) {
            scanf("%c%c%c", &hand[i].value, &hand[i].suit, &ch);
        }
        for (int i = 0; i < NUM_CARD; ++i) {
            scanf("%c%c%c", &deck[i].value, &deck[i].suit, &ch);
        }
        // Search.
        type_max = HIGHEST_CARD;
        for (int i = 0; i < 1 << NUM_CARD; ++i) {
            Search(i);
        }
        // Outputs.
        printf("Hand: ");
        for (int i = 0; i < NUM_CARD; ++i) {
            printf("%c%c ", hand[i].value, hand[i].suit);
        }
        printf("Deck: ");
        for (int i = 0; i < NUM_CARD; ++i) {
            printf("%c%c ", deck[i].value, deck[i].suit);
        }
        printf("Best hand: %s\n", str_write[type_max]);
    } 
    return 0;
}

bool IsSameSuit(Poker card[]) {
    for (int i = 1; i < NUM_CARD; ++i) {
        if (card[i].suit != card[0].suit) {
            return false;
        }
    }
    return true;
}

bool IsOrder(Poker card[]) {
    memset(count_value, 0, sizeof(count_value));
    for (int i = 0; i < NUM_CARD; ++i) {
        ++count_value[int_value[card[i].value]]; 
        if (card[i].value == 'A') {
            ++count_value[14];
        }
    }
    int num = 0;
    for (int i = 0; i < LIMITS_VALUES && num < 5; ++i) {
        if (count_value[i]) {
            ++num;
        } else {
            num = 0;
        }
    }
    if (num == 5) {
        return true;
    } else {
        return false;
    }
}

Type JudgeType(Poker card[]) {
    memset(count_value, 0, sizeof(count_value));
    memset(count_value_same, 0, sizeof(count_value_same));
    for (int i = 0; i < NUM_CARD; ++i) {
        ++count_value[int_value[card[i].value]];
    }
    for (int i = 1; i <= 13; ++i) {
        ++count_value_same[count_value[i]];
    }

    if (IsSameSuit(card) && IsOrder(card)) {
        return STRAIGHT_FLUSH;
    } else
    if (count_value_same[4]) {
        return FOUR_OF_A_KIND;
    } else
    if (count_value_same[3] && count_value_same[2]) {
        return FULL_HOUSE;
    } else
    if (IsSameSuit(card)) {
        return FLUSH;
    } else
    if (IsOrder(card)) {
        return STRAIGHT;
    } else
    if (count_value_same[3]) {
        return THREE_OF_A_KIND;
    } else
    if (count_value_same[2] == 2) {
        return TWO_PAIRS;
    } else
    if (count_value_same[2] == 1) {
        return ONE_PAIR;
    } else {
        return HIGHEST_CARD;
    }
}

void Search(int x) {
    Poker card[NUM_CARD];
    int top = 0;
    for (int i = 0; i < NUM_CARD; ++i) {
        if (x & (1 << i)) {
            card[top++] = hand[i];
        }
    }
    for (int i = 0; i < NUM_CARD && top < 5; ++i) {
        card[top++] = deck[i];
    }
    Type type = JudgeType(card);
    type_max = type > type_max ? type : type_max;
}








下载PDF

参考资料:刺客的博客


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值