UVa 131 - The Psychic Poker Player

36 篇文章 0 订阅

一手牌(规则请见:http://dpk888.com/school/discussions/%E4%B8%80%E6%89%8B%E7%89%8C%E7%9A%84%E7%89%8C%E5%9E%8B-poker-hands#per_page=10),枚举 + 模拟,关键是明白其桌子上的牌相当于一个栈,只有丢掉手里相应数量的牌才可以从栈中依次抽出相应数量的牌来维持手里始终有五张牌,依此枚举。

代码如下:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;

int poker_cmp(const void *a, const void *b)
{
    return strcmp((char *)a,(char *)b);
}
int ff, flag[11];
char a[6][3], b[11][3];
char s[9][20] = {"highest-card", "one-pair", "two-pairs", "three-of-a-kind",
                 "straight", "flush", "full-house", "four-of-a-kind", "straight-flush"
                };
int judge_flush() // 判断 同花
{
    int i;
    for(i = 0; i < 4; i++)
        if(a[i][1] != a[i + 1][1])
            return 0;
    return 1;
}
int judge_straight() // 判断 顺子
{
    if(a[0][0] == '1' && a[1][0] == ':' && a[2][0] == ';' && a[3][0] == '<' && a[4][0] == '=') // 注意特殊情况的判定,原因请见规则
        return 1;
    for(int i = 0; i < 4; i++)
        if(a[i][0] != a[i + 1][0] - 1)
            return 0;
    return 1;
}
int judge_kind_4() // 判断 四条
{
    int i;
    for(i = 0; i < 3; i++)
        if(a[i][0] != a[i + 1][0])
            break;
    if(i == 3)
        return 1;
    for(i = 1; i < 4; i++)
        if(a[i][0] != a[i + 1][0])
            return 0;
    return 1;
}
int judge_full_house() // 判断 葫芦
{
    if(a[0][0] == a[1][0] && a[1][0] == a[2][0] && a[3][0] == a[4][0])
        return 1;
    if(a[0][0] == a[1][0] && a[2][0] == a[3][0] && a[3][0] == a[4][0])
        return 1;
    return 0;
}
int judge_kind_3()// 判断 三条
{
    if(a[0][0] == a[1][0] && a[1][0] == a[2][0] )
        return 1;
    if(a[1][0] == a[2][0] && a[2][0] == a[3][0] )
        return 1;
    if(a[2][0] == a[3][0] && a[3][0] == a[4][0] )
        return 1;
    return 0;
}
int judge_two_pairs() // 判断 两对
{
    if(a[0][0] == a[1][0] && a[2][0] == a[3][0] )
        return 1;
    if(a[0][0] == a[1][0] && a[3][0] == a[4][0] )
        return 1;
    if(a[1][0] == a[2][0] && a[3][0] == a[4][0] )
        return 1;
    return 0;
}
int judge_pair() // 判断 一对
{
    for(int i = 0; i < 4; i++)
        if(a[i][0] == a[i + 1][0])
            return 1;
    return 0;
}
int solve()
{
    int flush = judge_flush();
    int straight = judge_straight();
    if(flush && straight)
        return 8;
    int kind_4 = judge_kind_4();
    if(kind_4)
        return 7;
    int full_house = judge_full_house();
    if(full_house)
        return 6;
    if(flush)
        return 5;
    if(straight)
        return 4;
    int kind_3 = judge_kind_3();
    if(kind_3)
        return 3;
    int two_pairs = judge_two_pairs();
    if(two_pairs)
        return 2;
    int pair = judge_pair();
    if(pair)
        return 1;
    return 0;
}
int subset_2()
{
    int ct = 0, f;
    for(int i = 0; i < 10; i++)
        if(flag[i])
            strcpy(a[ct++], b[i]);
        else if(ct == 5)
            break;
    qsort(a, 5, sizeof(a[0]), poker_cmp);
    f = solve();
    if(f > ff)
        ff = f;
    return ff;
}
int subset() // 枚举子集
{
    int fi[5];
    for(fi[0] = 0; fi[0] < 10; fi[0]++)
        for(fi[1] = fi[0] + 1; fi[1] < 10; fi[1]++)
            if(fi[0] != fi[1])
                for(fi[2] = fi[1] + 1; fi[2] < 10; fi[2]++)
                    if(fi[0] != fi[2] && fi[1] != fi[2])
                        for(fi[3] = fi[2] + 1; fi[3] < 10; fi[3]++)
                            if(fi[0] != fi[3] && fi[1] != fi[3] && fi[2] != fi[3])
                                for(fi[4] = fi[3] + 1; fi[4] < 10; fi[4]++)
                                    if(fi[0] != fi[4] && fi[1] != fi[4] && fi[2] != fi[4] && fi[3] != fi[4])
                                    {
                                        int fct = 0;
                                        for(int i = 0; i < 5; i++)
                                            if(fi[i] < 5)
                                                ++fct;
                                        if(fi[4] >= 10 - fct) // 保证只有丢掉相应数量的手牌才可以从桌子上抽取相应数量的牌
                                            break;
                                        memset(flag, 0, sizeof(flag));
                                        flag[fi[0]] = 1;
                                        flag[fi[1]] = 1;
                                        flag[fi[2]] = 1;
                                        flag[fi[3]] = 1;
                                        flag[fi[4]] = 1;
                                        int f = subset_2();
                                        if(f == 8)
                                            return 8;
                                    }
    return 0;
}
int main()
{
#ifdef test
    freopen("in.txt", "r", stdin);
#endif
    char str[50];
    while(gets(str) != NULL)
    {
        for(int i = 0; i < 10; i++)
            sscanf(str + 3 * i, "%[^ ]",b[i]);
        printf("Hand: ");
        for(int i = 0; i < 5; i++)
            printf("%s ", b[i]);
        printf("Deck: ");
        for(int i = 5; i < 10; i++)
            printf("%s ", b[i]);
        printf("Best hand: ");
        for(int i = 0; i < 10; i++) // 为了判断方便,可以将‘A’‘T’‘J’‘Q’‘K’转化为‘1’‘:’‘“’‘<’‘=',其ASCll码依次增加
            if(b[i][0] == 'A')
                b[i][0] = '1';
            else if(b[i][0] == 'T')
                b[i][0] = ':';
            else if(b[i][0] == 'J')
                b[i][0] = ';';
            else if(b[i][0] == 'Q')
                b[i][0] = '<';
            else if(b[i][0] == 'K')
                b[i][0] = '=';
        ff = 0;
        subset();
        printf("%s\n", s[ff]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值