超级传送门:http://projecteuler.net/problem=54
刚看到题目描述,就联想到天津Regional的A题麻将那题,可惜没能AC,遗憾了好久。
这题比麻将那题要简单一些,规则描述比较清楚,要比较两手梭哈牌的大小,我用了hash来存牌,定义了各种判定判断函数来进行判断。
代码量还是比较大的,差不多600行,写的过程中很容易错。Unix/Linux设计思想——小即是美、每个函数的功能尽可能简单的专一,用这种设计思想来写,就不容易出错了。
代码如下:
#include <cstdio> #include <cstring> #define COLOR_H 0 #define COLOR_C 1 #define COLOR_S 2 #define COLOR_D 3 using namespace std; char PACards[5][3]; char PBCards[5][3]; int PAHash[4][13]; int PBHash[4][13]; inline int calcPokerIndex(char card) { if (card >= '2' && card <= '9') return card - '2'; if (card == 'T') return 8; if (card == 'J') return 9; if (card == 'Q') return 10; if (card == 'K') return 11; if (card == 'A') return 12; } void doHash(char cards[5][3], int hash[4][13]) { memset(hash, 0, sizeof(int) * 4 * 13); for (int i = 0; i <= 4; i++) { int pokerIndex = calcPokerIndex(cards[i][0]); switch (cards[i][1]) { case 'H': hash[COLOR_H][pokerIndex] = 1; break; case 'C': hash[COLOR_C][pokerIndex] = 1; break; case 'S': hash[COLOR_S][pokerIndex] = 1; break; case 'D': hash[COLOR_D][pokerIndex] = 1; break; default: break; } } } int getMaxPoker(int hash[4][13], int which) { int cnt = 0; int tmpHash[13]; memset(tmpHash, 0, sizeof(tmpHash)); for (int i = 0; i <= 3; i++) { for (int j = 0; j <= 12; j++) { if (hash[i][j]) tmpHash[j]++; } } for (int i = 12; i >= 0; i--) { while (tmpHash[i]) { tmpHash[i]--; cnt++; if (cnt == which) return i; } } } int isOnePair(int hash[4][13]) { int count = 0; int pairCount = 0; int firstPairVal = 0; for (int j = 0; j <= 12; j++) { count = 0; for (int i = 0; i <= 3; i++) { if (hash[i][j]) count++; } if (count == 2) { pairCount++; firstPairVal = j; } } if (pairCount == 1) return firstPairVal; return -1; } int isTwoPairs(int hash[4][13]) { int count = 0; int pairCount = 0; int firstPairVal = 0; int secondPairVal = 0; for (int j = 0; j <= 12; j++) { count = 0; for (int i = 0; i <= 3; i++) { if (hash[i][j]) count++; } if (count == 2) { pairCount++; if (pairCount == 1) firstPairVal = j; else secondPairVal = j; } } if (pairCount == 2) return 13 * secondPairVal + firstPairVal; return -1; } int isThreeOfAKind(int hash[4][13]) { int count = 0; for (int j = 0; j <= 12; j++) { count = 0; for (int i = 0; i <= 3; i++) { if (hash[i][j]) count++; } if (count == 3) return j; } return -1; } int isStraight(int hash[4][13]) { int tmpHash[13]; memset(tmpHash, 0, sizeof(tmpHash)); for (int i = 0; i <= 3; i++) { for (int j = 0; j <= 12; j++) { if (hash[i][j]) tmpHash[j]++; } } for (int i = 0; i <= 8; i++) { if (tmpHash[i] && tmpHash[i + 1] && tmpHash[i + 2] && tmpHash[i + 3] && tmpHash[i + 4]) return i + 4; } return -1; } int isFlush(int hash[4][13]) { int count = 0; for (int i = 0; i <= 3; i++) { count = 0; for (int j = 0; j <= 12; j++) { if (hash[i][j]) count++; } if (count == 5) return 1; } return -1; } int isFullHouse(int hash[4][13]) { int count = 0; int pairVal = -1; int threeVal = -1; for (int j = 0; j <= 12; j++) { count = 0; for (int i = 0; i <= 3; i++) { if (hash[i][j]) count++; } if (count == 2) pairVal = j; if (count == 3) threeVal = j; } if (pairVal == -1 || threeVal == -1) return -1; return 13 * threeVal + pairVal; } int isFourOfAKind(int hash[4][13]) { int count = 0; for (int j = 0; j <= 12; j++) { count = 0; for (int i = 0; i <= 3; i++) { if (hash[i][j]) count++; } if (count == 4) return j; } return -1; } int isStraightFlush(int hash[4][13]) { for (int i = 0; i <= 3; i++) { for (int j = 0; j <= 8; j++) { if (hash[i][j] && hash[i][j + 1] && hash[i][j + 2] && hash[i][j + 3] && hash[i][j + 4]) return j + 4; } } return -1; } int isRoyalFlush(int hash[4][13]) { for (int i = 0; i <= 3; i++) { if (hash[i][8] && hash[i][9] && hash[i][10] && hash[i][11] && hash[i][12]) return 1; } return -1; } int checkDefault(int PAHash[4][13], int PBHash[4][13]) { for (int i = 1; i <= 5; i++) { int PAPokerVal = getMaxPoker(PAHash, i); int PBPokerVal = getMaxPoker(PBHash, i); if (PAPokerVal != PBPokerVal) return PAPokerVal > PBPokerVal; } } int checkOnePair(int PAHash[4][13], int PBHash[4][13]) { int PARetVal; int PBRetVal; PARetVal = isOnePair(PAHash); PBRetVal = isOnePair(PBHash); if (PARetVal != -1 && PBRetVal == -1) return 1; if (PARetVal == -1 && PBRetVal != -1) return 0; if (PARetVal != -1 && PBRetVal != -1) { if (PARetVal != PBRetVal) return PARetVal > PBRetVal; for (int i = 1; i <= 5; i++) { int PAPokerVal = getMaxPoker(PAHash, i); int PBPokerVal = getMaxPoker(PBHash, i); if (PAPokerVal != PBPokerVal) return PAPokerVal > PBPokerVal; } } return -1; } int checkTwoPairs(int PAHash[4][13], int PBHash[4][13]) { int PARetVal; int PBRetVal; PARetVal = isTwoPairs(PAHash); PBRetVal = isTwoPairs(PBHash); if (PARetVal != -1 && PBRetVal == -1) return 1; if (PARetVal == -1 && PBRetVal != -1) return 0; if (PARetVal != -1 && PBRetVal != -1) { if (PARetVal != PBRetVal) return PARetVal > PBRetVal; for (int i = 1; i <= 5; i++) { int PAPokerVal = getMaxPoker(PAHash, i); int PBPokerVal = getMaxPoker(PBHash, i); if (PAPokerVal != PBPokerVal) return PAPokerVal > PBPokerVal; } } return -1; } int checkThreeOfAKind(int PAHash[4][13], int PBHash[4][13]) { int PARetVal; int PBRetVal; PARetVal = isThreeOfAKind(PAHash); PBRetVal = isThreeOfAKind(PBHash); if (PARetVal != -1 && PBRetVal == -1) return 1; if (PARetVal == -1 && PBRetVal != -1) return 0; if (PARetVal != -1 && PBRetVal != -1) { if (PARetVal != PBRetVal) return PARetVal > PBRetVal; for (int i = 1; i <= 5; i++) { int PAPokerVal = getMaxPoker(PAHash, i); int PBPokerVal = getMaxPoker(PBHash, i); if (PAPokerVal != PBPokerVal) return PAPokerVal > PBPokerVal; } } return -1; } int checkStraight(int PAHash[4][13], int PBHash[4][13]) { int PARetVal; int PBRetVal; PARetVal = isStraight(PAHash); PBRetVal = isStraight(PBHash); if (PARetVal != -1 && PBRetVal == -1) return 1; if (PARetVal == -1 && PBRetVal != -1) return 0; if (PARetVal != -1 && PBRetVal != -1) { if (PARetVal != PBRetVal) return PARetVal > PBRetVal; for (int i = 2; i <= 5; i++) { int PAPokerVal = getMaxPoker(PAHash, i); int PBPokerVal = getMaxPoker(PBHash, i); if (PAPokerVal != PBPokerVal) return PAPokerVal > PBPokerVal; } } return -1; } int checkFlush(int PAHash[4][13], int PBHash[4][13]) { int PARetVal; int PBRetVal; PARetVal = isFlush(PAHash); PBRetVal = isFlush(PBHash); if (PARetVal != -1 && PBRetVal != -1) { if (PARetVal == 1 && PBRetVal == 1) { for (int i = 1; i <= 5; i++) { int PAPokerVal = getMaxPoker(PAHash, i); int PBPokerVal = getMaxPoker(PBHash, i); if (PAPokerVal != PBPokerVal) return PAPokerVal > PBPokerVal; } } else return PARetVal > PBRetVal; } return -1; } int checkFullHouse(int PAHash[4][13], int PBHash[4][13]) { int PARetVal; int PBRetVal; PARetVal = isFullHouse(PAHash); PBRetVal = isFullHouse(PBHash); if (PARetVal != -1 && PBRetVal == -1) return 1; if (PARetVal == -1 && PBRetVal != -1) return 0; if (PARetVal != -1 && PBRetVal != -1) return PARetVal > PBRetVal; return -1; } int checkFourOfAKind(int PAHash[4][13], int PBHash[4][13]) { int PARetVal; int PBRetVal; PARetVal = isFourOfAKind(PAHash); PBRetVal = isFourOfAKind(PBHash); if (PARetVal != -1 && PBRetVal == -1) return 1; if (PARetVal == -1 && PBRetVal != -1) return 0; if (PARetVal != -1 && PBRetVal != -1) { if (PARetVal == PBRetVal) { int PASingleVal = -1; int PBSingleVal = -1; for (int i = 1; i <= 5; i++) { int pokerVal = getMaxPoker(PAHash, i); if (pokerVal != PARetVal) { PASingleVal = pokerVal; break; } } for (int i = 1; i <= 5; i++) { int pokerVal = getMaxPoker(PBHash, i); if (pokerVal != PBRetVal) { PBSingleVal = pokerVal; break; } } return PASingleVal > PBSingleVal; } else return PARetVal > PBRetVal; } return -1; } int checkStraightFlush(int PAHash[4][13], int PBHash[4][13]) { int PARetVal; int PBRetVal; PARetVal = isStraightFlush(PAHash); PBRetVal = isStraightFlush(PBHash); if (PARetVal != -1 && PBRetVal == -1) return 1; if (PARetVal == -1 && PBRetVal != -1) return 0; if (PARetVal != PBRetVal) return PARetVal > PBRetVal; return -1; } int checkRoyalFlush(int PAHash[4][13], int PBHash[4][13]) { int PARetVal; int PBRetVal; PARetVal = isRoyalFlush(PAHash); PBRetVal = isRoyalFlush(PBHash); if (PARetVal != -1 && PBRetVal == -1) return 1; if (PARetVal == -1 && PBRetVal != -1) return 0; return -1; } int beats(char PA[5][3], char PB[5][3]) { doHash(PA, PAHash); doHash(PB, PBHash); int retVal; retVal = checkRoyalFlush(PAHash, PBHash); if (retVal != -1) return retVal; retVal = checkStraightFlush(PAHash, PBHash); if (retVal != -1) return retVal; retVal = checkFourOfAKind(PAHash, PBHash); if (retVal != -1) return retVal; retVal = checkFullHouse(PAHash, PBHash); if (retVal != -1) return retVal; retVal = checkFlush(PAHash, PBHash); if (retVal != -1) return retVal; retVal = checkStraight(PAHash, PBHash); if (retVal != -1) return retVal; retVal = checkThreeOfAKind(PAHash, PBHash); if (retVal != -1) return retVal; retVal = checkTwoPairs(PAHash, PBHash); if (retVal != -1) return retVal; retVal = checkOnePair(PAHash, PBHash); if (retVal != -1) return retVal; return checkDefault(PAHash, PBHash); } int main() { freopen("poker.txt", "r", stdin); int ans = 0; while(scanf("%s", PACards[0]) > 0) { for (int i = 1; i <= 4; i++) scanf("%s", PACards[i]); for (int i = 0; i <= 4; i++) scanf("%s", PBCards[i]); if (beats(PACards, PBCards)) ans++; } printf("%d\n", ans); return 0; }