超级传送门: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;
}