题目链接地址:
题目描述:
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
****************************************************************/