九度OJ-题目1355:扑克牌顺子

题目链接地址:

九度OJ-题目1355:扑克牌顺子


题目描述:
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。
现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何。为了方便起见,你可以认为大小王是0。

输入:
输入有多组数据。
每组数据包含两行,第一行输入一个正数n(0<=n<=14),表示从扑克牌中抽出的扑克牌数。接下来的一行输入n个数,表示从这幅扑克牌中抽出的牌。如果n=0,则结束输入。

输出:
对应每组数据,如果抽出的牌是顺子,则输出“So Lucky!”。否则,输出“Oh My God!”。

样例输入:
5
3  5  1  0  4
5
3  5  4  7  6
5
3  5  7  4  8
0

样例输出:
So Lucky!
So Lucky!
Oh My God!


解题思路:

从一副扑克牌中抽出n(0 <= n <= 14)张扑克牌,如果这n张扑克牌能够组成一个公差为1的等差数列,则可以证明这些扑克牌就是顺子。扑克牌中大小王的作用是可以看成任何数字,补齐等差数列中缺失的数字。所以我的想法如下:
(1)对抽出的扑克牌进行排序;
(2)统计抽出扑克牌中大小王的数目;
(3)将大小王替换为任意数字插入到剩余扑克牌(剩余扑克牌是指所抽出的扑克牌中除去大小王的那部分扑克牌)中,

         如果抽出的扑克牌能构成一个公差为1的等差数列,就说明抽出的扑克牌是顺子。
现在的问题就是如何将大小王替换为任意数?
换个角度来思考这个问题,请脑补以下画面:
假设现在有14个箱子,这些箱子编号为0 ~ 13。
对抽出的n张扑克牌进行如下处理:
(1)先将大小王暂时放到0号箱子中;
(2)然后将其余普通牌放到与该牌数字相同的箱子中;
(3)从编号最小的普通牌开始,依次查看相隔最近的两张普通牌,如果这两张普通牌之间还有空箱子,就从0号箱中拿出一张

         王牌放入到该箱中。待所有的王牌放置完毕后,如果装有扑克牌的箱子编号是连续的,那么就说明抽出的扑克牌是顺子,

         否则扑克牌就不是顺子。
需要注意的是如果抽出的扑克牌中出现了相同的牌,是无法构成顺子的。
例如:如果抽出的扑克牌是1,2,2 ,3,4
那么这些扑克牌是无法构成顺子的。
AC代码如下:

#include<stdio.h>
 
/**
* 输入抽出的扑克牌序列
* @param poker  用于存储扑克牌输入序列的数组
* @param n  抽出的扑克牌的张数
* @return void
*/
void inputPoker(int poker[],int n)
{
  int i;
  for(i = 0;i < n;i++)
  {
      scanf("%d",&poker[i]);
  }
}
 
/**
* 判断抽出的扑克牌是不是顺子
* @param poker  抽出的扑克牌
* @param n  抽出的扑克牌的张数
* @return bool 如果抽出的扑克牌是顺子,则返回true,否则返回false。
*/
bool isPokerStraight(int poker[],int n)
{
  bool isStraight;
  int i,j;
  int temp;
  int countKing = 0;
  int gap;                          // 排好序的普通扑克牌序列中相邻两张扑克牌之间的间距
  int gapSum = 0;                   // 排除大小王以后剩余普通牌的间距之和
  // 对抽出的扑克牌进行排序
  for(i = n - 1;i > 0;i--)
  {
      for(j = 0;j < i;j++)
      {
        if(poker[j] > poker[j + 1])
        {
          temp = poker[j];
          poker[j] = poker[j + 1];
          poker[j + 1] = temp;
        }
      }
  }
  // 统计牌中大小王的张数
  i = 0;
  while(i < n && 0 == poker[i])
  {
      i++;
      countKing++;
  }
  // 统计抽出的扑克牌中的间距
  while(i < n - 1)
  {
      gap = poker[i + 1] - poker[i];
      if(gap > 0)
      {
         gapSum = gapSum + gap;
      }
      else                          // 排除大小王后的剩余普通牌中出现了相同的牌,无法构成顺子
      {
         isStraight = false;
         return isStraight;
      }
      i++;
  }
  // n - countKing - 1是排除大小王后剩余普通扑克牌组成顺子的合法间距
  // gapSum - countKing是将大小王插入到普通扑克牌序列后还剩下的间距
  // 一张大小王能够消除1个间距
  // 例如:2 与 4 相差2个间距,插入一张大小王并将该大小王看成是3后,可以认为2与4之间只相差一个间距了
  if(gapSum - countKing > n - countKing - 1)
     isStraight = false;
  else
     isStraight = true;
  return isStraight;
}
 
int main()
{
    int n;
    int poker[15];
    bool isStraight;
    while(EOF != scanf("%d",&n) && 0 != n)
    {
       inputPoker(poker,n);
       isStraight = isPokerStraight(poker,n);
       if(true == isStraight)
          printf("So Lucky!\n");
       else
          printf("Oh My God!\n");
    }
    return 0;
}
 
/**************************************************************
    Problem: 1355
    User: blueshell
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1020 kb
****************************************************************/

猜你喜欢

转载自blog.csdn.net/pengyan0812/article/details/46482403