The Psychic Poker Player
The Psychic Poker Player |
In 5-card draw poker, a player is dealt a hand of five cards (which may be looked at). The player may then discard between zero and five of his or her cards and have them replaced by the same number of cards from the top of the deck (which is face down). The object is to maximize the value of the final hand. The different values of hands in poker are given at the end of this problem.
Normally the player cannot see the cards in the deck and so must use probability to decide which cards to discard. In this problem, we imagine that the poker player is psychic and knows which cards are on top of the deck. Write a program which advises the player which cards to discard so as to maximize the value of the resulting hand.
Input and Output
Input will consist of a series of lines, each containing the initial five cards in the hand then the first five cards on top of the deck. Each card is represented as a two-character code. The first character is the face-value (A=Ace, 2-9, T=10, J=Jack, Q=Queen, K=King) and the second character is the suit (C=Clubs, D=Diamonds, H=Hearts, S=Spades). Cards will be separated by single spaces. Each input line will be from a single valid deck, that is there will be no duplicate cards in each hand and deck.
Each line of input should produce one line of output, consisting of the initial hand, the top five cards on the deck, and the best value of hand that is possible. Input is terminated by end of file.
Use the sample input and output as a guide. Note that the order of the cards in the player's hand is irrelevant, but the order of the cards in the deck is important because the discarded cards must be replaced from the top of the deck. Also note that examples of all types of hands appear in the sample output, with the hands shown in decreasing order of value.
Sample Input
TH JH QC QD QS QH KH AH 2S 6S 2H 2S 3H 3S 3C 2D 3D 6C 9C TH 2H 2S 3H 3S 3C 2D 9C 3D 6C TH 2H AD 5H AC 7H AH 6H 9H 4H 3C AC 2D 9C 3S KD 5S 4D KS AS 4C KS AH 2H 3C 4H KC 2C TC 2D AS AH 2C 9S AD 3C QH KS JS JD KD 6C 9C 8C 2D 7C 2H TC 4C 9S AH 3D 5S 2H QD TD 6S KH 9H AD QH
Sample Output
Hand: TH JH QC QD QS Deck: QH KH AH 2S 6S Best hand: straight-flush Hand: 2H 2S 3H 3S 3C Deck: 2D 3D 6C 9C TH Best hand: four-of-a-kind Hand: 2H 2S 3H 3S 3C Deck: 2D 9C 3D 6C TH Best hand: full-house Hand: 2H AD 5H AC 7H Deck: AH 6H 9H 4H 3C Best hand: flush Hand: AC 2D 9C 3S KD Deck: 5S 4D KS AS 4C Best hand: straight Hand: KS AH 2H 3C 4H Deck: KC 2C TC 2D AS Best hand: three-of-a-kind Hand: AH 2C 9S AD 3C Deck: QH KS JS JD KD Best hand: two-pairs Hand: 6C 9C 8C 2D 7C Deck: 2H TC 4C 9S AH Best hand: one-pair Hand: 3D 5S 2H QD TD Deck: 6S KH 9H AD QH Best hand: highest-card
题意是给你手上五张牌,桌子上五张牌。你有一次机会可以舍弃手上任意k张牌,并从桌子上顶部开始拿k张牌,输出手上的牌和桌子上的牌和你能得到的最大组合
直接枚举一遍五张牌的状态然后舍弃和抽取,找出最大的组合。用5位二进制数表示五张牌的状态,1代表丢弃,0代表保留,用变量i从0-31表示总共32种状态
#include <iostream>
#include <algorithm>
using namespace std;
//枚举常量,按照牌的大小,从大到小
enum BestHand{straight_flushs,four_of_a_kind,full_house,flushs,straight,
three_of_a_kind, two_pairs, one_pair};
string str[8] = {"straight-flush","four-of-a-kind","full-house","flush","straight",
"three-of-a-kind", "two-pairs", "one-pair"};
struct c //每张牌的数据,数值大小和花色
{
int value;
char suit;
};
int getValue(char ch) //牌的大小2-A,转换成由数字1-13表示,便于比较和排序
{
switch(ch){
case 'A':
return 13;
case 'T':
return 9;
case 'J':
return 10;
case 'Q':
return 11;
case 'K':
return 12;
default:
return 1+ch-'2';
}
}
c deck[5];
c hand[5];
c cp[5];
int cmp(const c & a, const c &b) //牌的排序方式,用作sort函数的参数
{
return a.value < b.value;
}
//牌判断前都是按大小从小到大排好序了
int isSAF() //判断,同花、顺子、同花顺
{
int s = 1, f = 1; //s(straight)代表是否顺子,f(flush)代表同花
//判断是否为顺子,因A代表的是13,所以第二个条件是对于A 2 3 4 5特判
for(int i = 0; i < 4; i++)
if(cp[i+1].value - cp[i].value != 1 && !(i==3 && cp[i].value==4 && cp[i+1].value == 13)){
s = 0;
break;
}
for(int i = 1; i < 5; i++)
if(cp[i].suit != cp[0].suit){
f = 0;
break;
}
if(s && f)
return straight_flushs;
else if(f)
return flushs;
else if(s)
return straight;
else
return 100; //什么都没有返回一个不可能的值,取大的
}
int isFAK() //判断炸
{
for(int i = 1; i < 4; i++){
if(cp[i].value != cp[0].value)
break;
if(i == 3) return four_of_a_kind;
}
for(int i = 3; i >= 1; i--){
if(cp[i].value != cp[4].value)
break;
if(i == 1) return four_of_a_kind;
}
return 100;
}
int isTTO()//判断葫芦,三条,两对,一对
{
int three = 0, pairs = 0;
for(int i = 0; i < 3; i++)
if(cp[i].value == cp[i+1].value && cp[i+1].value == cp[i+2].value)
three = 1;
//判断对的时候注意如果是三条就不能算对了
for(int i = 0; i < 4; i++)
if(cp[i].value == cp[i+1].value && cp[i+1].value != cp[i+2].value && (!i || (cp[i-1].value != cp[i].value)))
pairs++;
if(three && pairs)
return full_house;
else if(three)
return three_of_a_kind;
else if(pairs == 2)
return two_pairs;
else if(pairs)
return one_pair;
else
return 100;
}
int main()
{
char a, b;
while(cin >> a >> b){
cout << "Hand: ";
for(int i = 0; i < 5; i++){
if(i)
cin >> a >> b;
hand[i].value = getValue(a);
hand[i].suit = b;
cout << a << b << " ";
}
cout << "Deck: ";
for(int i = 0; i < 5; i++){
cin >> a >> b;
deck[i].value = getValue(a);
deck[i].suit = b;
cout << a << b << " ";
}
int ans = 100;
cout << "Best hand: ";
for(int i = 0; i < 32; i++){ //用5个二进制数表示手上牌的状态,1代表丢弃换牌,0表示不换
int used = 0; //表示换了多少张牌,从左边开始换(也就deck上的top)
for(int j = 0; j < 5; j++) cp[j] = hand[j];
for(int t = 0; t < 5; t++){
if((i>>t)&1) cp[t] = deck[used++];
}
sort(cp, cp+5, cmp); //将牌从小排到大
ans = min(ans, isSAF());
ans = min(ans, isFAK());
ans = min(ans, isTTO());
}
if(ans == 100) //什么都没有输出highest-card
cout <<"highest-card\n";
else
cout << str[ans] << endl;
}
return 0;
}