华为机试—计算麻将的番数(高级题160分)

一.题目如下

二.题目分析

麻将和牌有两种形式,即:

模式1 :11,11,11,11,11,11,11
模式2: 11,123,123,123,123(全部或者部分123可以被111,1111替代)     

注:123=连续3张同花色牌,如4D5D6D。111=3张同样的牌,如3T3T3T。
    条=T,筒=D

模式1即称之为“巧7对”,一组牌刚好是7对牌。但是这里有一个疑问,“对”能否重复,即“杠”能否能当作2“对”(即题目中的“四归一”)。正常的和牌最后手中总共有14张牌,实际生活中以模式1和牌并且计算带“杠”的翻番是不可能的。

模式2有很多变种。首先123是指连续花色的3张牌,诸如“1条2条3条”或“4筒5筒6筒”等等。也可以是三种同花色的,如“1筒1筒1筒或“9条9条9条”。倘若你有了或者这样的一组牌,别人又出了一张同样的牌或者你接到一张同样的牌,这个时候就是“四归一”或者“杠”了。

日常生活中,实际上每一个“杠”,你都需要声明(不管是明“杠”或是暗“杠”),然后再接一张牌,也就是说,随着你每声明你有1个杠,最后和牌的时候你的牌都递增1张。假设这样的场景,你手中有13张牌,其中有一组牌“2条2条2条”,这时你又接到一张“2条”,那么你有两个选择。(1)声明你接到一个“杠”,即暗杠,然后你再接一张牌,倘若你此时和牌,那么你的牌有13+1+1=15张,当然这不是巧7对;倘若不和牌,你必须打出去一张并接着打下去。(2)倘若你不声明,又刚好组成了巧7对,那你可以和牌了此时共有14张牌,但这“2条2条2条2条”并不是“杠”因为你并未声明,你只能当两对使用。倘若你没有和牌,那你就必须打出去一张牌了,即手上只有13张牌了。

总的来说,实际生活中,你手中出现了“四归一”,要么声明,然后你多接一张牌,按照模式2和牌。要么你不声明,按照模式1和牌。

但此处的题目并没有具体说明,处于严谨的考虑,模式1带“四归一”和牌,即没有声明的“杠”,我也是是计算了番数的。

程序中和牌方式和番数的举例如下:

模式1:

  1T1T,2D2D,3T3T,4D4D,5D5D,6D6D,7T7T.  巧7对:2番
  1T1T, 2D2D,3T3T,4D4D,5D5D,6D6D6D6D.  巧7对+1“四归一”== 2+2=4番
  1T1T, 2D2D,3T3T3T3T ,5D5D,6D6D6D6D.  巧7对+2“四归一”== 2+4=6番
  1T1T, 2D2D2D2D,3T3T3T3T , 6D6D6D6D.  巧7对+3“四归一”== 2+6=8番

模式2:

  1T1T,2D3D4D,4D5D6D,7D8D9D,2T3T4T.       0番
  1T1T,2D3D4D,4D5D6D,7D8D9D,1T2T3T.       1番
  1T1T,2D2D2D2D,4D5D6D,7D8D9D,2T3T4T.     2番
  1T1T,2D2D2D2D,4D5D6D,7D8D9D,1T2T3T.     1“四归一”+卡2条==2+1=3番
  1T1T,2D2D2D2D,5T5T5T,7D8D9D,1T2T3T.     1“四归一”+卡2条==2+1=3番

模式2中,全部或者部分连续三张同花色的一组牌如“2T3T4T或“7D8D9D”都可以被同花色的相同三张牌如“5T5T5T” 替代,如上。甚至是连续4张相同牌即“四归一”替代,如下,当然后者计算番数。

  1T1T,2D2D2D,5D5D5D5D,7D7D7D7D,5T6T7T.      2“四归一”==4番
  1T1T,2D2D2D2D,5D5D5D5D,7D7D7D7D,1T2T3T.    3“四归一”+卡2条==6+1=7番
  1T1T,2D2D2D2D,5D5D5D5D,7D7D7D7D,3T3T3T3T.  4“四归一”==8番
  1T1T,2D2D2D2D,4D5D6D,1T2T3T,1T2T3T.        2+1+1=4番
  1T1T,2D2D2D2D,1T2T3T,1T2T3T,1T2T3T.        2+1+1+1=5番

三.程序思路

输入:

最多18张牌,故最大存储空间为2*18+4‘,‘+1‘.‘+‘\0‘=42

遍历字符串:

       1)判断是否出现连续三种同花色牌(ka),如形如“4D5D6D”。在这种情况下,判断(ka2tiao)是否出现卡2条即“1T2T3T”。
       2) 判断(lian3)是否出现连续3张相同牌如“7T7T7T”
       3) 判断(gang)是否出现“四归一”并计数。

输出:

   1) 倘若连续三张同花色牌4D5D6D一组牌出现,或者连续三张相同牌7T7T7T的一组牌牌出现,或者“四归一”出现了4次,
      那么和牌是按照模式2和牌。
         番数=“卡2条”次数*1 + “四归一”的次数*2
   2) 模式1即巧7对和牌
         番数=2+2*“四归一”的次数

四.程序代码

#include <iostream>
#include <string>
using namespace std;

int main()
{
    int fan;
    int i;
    int gang;
    int ka,lian3,ka2tiao; 

    char s[42];  

	while(cin>>s){

		fan=gang=ka=lian3=ka2tiao=0;
		int len = strlen(s);

		for(i=0;i<len;i++)
		{
			if(s[i]<='9'&&s[i]>='1')
			{
				if(s[i]==s[i+2]&&s[i+2]==s[i+4]&&s[i+4]==s[i+6]&&(s[i+8]==','||s[i+8]=='.'))//判断是否有杠并计数,即四归一如1D1D1D1D
					gang++;
				else if((s[i]==s[0]||s[i-1]==',')&&s[i]==s[i+2]&&s[i+2]==s[i+4]&&(s[i+6]==','||s[i+6]=='.'))//判断是否有连3,即如2D2D2D
					lian3=1;
				else if((s[i]+2)==(s[i+2]+1)&&(s[i+2]+1)==(s[i+4])&&(s[i+6]==','||s[i+6]=='.'))//判断是否有卡,即nT(n+1)T(n+2)T
				{
					ka=1;
					if(s[i]=='1'&&s[i+1]=='T')
						ka2tiao++;//判断卡2条-----1T2T3T 个数
				}
		   }
		}

		if(ka||lian3||gang==4)//存在nT(n+1)T(n+2)T或2D2D2D的或者4个“四归一”情况,必定是第2种和牌方式
			fan=ka2tiao*1+gang*2;
		else
			fan=2+gang*2;//巧七对的和牌方式  

		cout<<fan<<endl;
	}

    return 0;
} 

五.测试结果

时间: 2024-10-08 20:18:47

华为机试—计算麻将的番数(高级题160分)的相关文章

2015华为机试—— 计算二进制数的0的个数

描述: 输入一个10进制数字,请计算该数字对应二进制中0的个数,注意左数第一个1之前的所有0都不需要计算.不需要考虑负数的情况. 题目类别:位运算 难度:初级 运行时间限制:无限制 内存限制:无限制 阶段:入职前练习 输入: 要计算的十进制非负数 输出: 二进制中第一个1之后0 的个数 样例输入: 2 样例输出: 1 解题思路: 对于给定的数n,使用位运算:n=n&(n-1)可计算出对应二进制中1的个数,为count1.将input=n,input=input>>1逐个获取input中

华为机试-求最大连续bit数

题目描述功能: 求一个byte数字对应的二进制数字中1的最大连续数,例如3的二进制为00000011,最大连续2个1 输入: 一个byte型的数字 输出: 无 返回: 对应的二进制数字中1的最大连续数输入描述:输入一个byte数字输出描述:输出转成二进制之后连续1的个数示例1输入 3输出 2 程序实现 import java.util.Scanner; /** * 功能: 求一个byte数字对应的二进制数字中1的最大连续数,例如3的二进制为00000011,最大连续2个1 * * 输入: 一个b

华为机试—输出含“23”的数

输入一行数字:123 423 5645 875 186523 在输入第二行:23 将第一行中含有第二行中"23"的数输出并排序 结果即:123 423 186523 /* 先排序,顺序遍历每个数字,看是否含有23 */ #include<stdio.h> #include<stdlib.h> int cmp(const void *a,const void *b) { return *(int*)a-*(int*)b; } int main(int argc,

2015华为机试——计算两个正整数的最大公约数和最小公倍数

题目描述: 接口说明 原型: long getMaxDivisor(long lFirstInput, long lSecondInput); 输入参数: int first: 第一个整数; int second: 第二个整数; 返回值: 最大公约数 long getMinMultiple(long lFirstInput, long lSecondInput); 输入参数: int first: 第一个整数; int second: 第二个整数; 返回值: 最小公倍数 解题思路:使用辗转相除法

华为机试-计算字符串的相似度

题目描述 对于不同的字符串,我们希望能有办法判断相似程度,我们定义了一套操作方法来把两个不相同的字符串变得相同,具体的操作方法如下: 1 修改一个字符,如把"a"替换为"b". 2 增加一个字符,如把"abdd"变为"aebdd". 3 删除一个字符,如把"travelling"变为"traveling". 比如,对于"abcdefg"和"abcdef&qu

2015华为机试——计算整数的位数

题目描述: 输入一个五位以内(包括5位)的正整数,(1)判断它是一个几位数:(2)逆序输出其各位数字. 输入:多组数据,每组一行 输出:对应一行输出 样例输入:56439 样例输出:5 93465 解题思路:使用StringBuffer的reverse方法即可. 代码如下: public static void main(String[] args) { Scanner sc=new Scanner(System.in); while (sc.hasNext()) { String input=

华为机试 计算字符个数

题目描述 写出一个程序,接受一个由字母和数字组成的字符串,和一个字符,然后输出输入字符串中含有该字符的个数.不区分大小写. 输入描述: 输入一个有字母和数字以及空格组成的字符串,和一个字符. 输出描述: 输出输入字符串中含有该字符的个数. 输入 ABCDEF A 输出 1 #include<iostream> #include<string.h> using namespace std; int main(){ string s; char ss; int count=0; cin

华为机试—取石子游戏(高级题160分)

Problem Description 1堆石子有n个,两人轮流取.先取者第1次可以取任意多个,但不能全部取完.以后每次取的石子数不能超过上次取子数的2倍.取完者胜.先取者负输出"Secondwin".先取者胜输出"Firstwin". Input 输入有多组.每组第1行是2<=n<2^31.n=0退出. Output 先取者负输出"Secondwin". 先取者胜输出"Firstwin". 参看Sample Ou

华为机试—添加符号使等式成立(高级题160分)

输入一个正整数X,在下面的等式左边的数字之间添加+号或者-号或者不填,使得等式成立. 1 2 3 4 5 6 7 8 9 = X 比如: 12-34+5-67+89 = 5 1+23+4-5+6-7-8-9 = 5 请编写程序,统计满足输入整数的所有等式个数. 输入:       正整数,等式右边的数字 输出:       使该等式成立的个数 样例输入:5 样例输出:21 #include <iostream> #include <string> using namespace s