这是个中国麻将的问题,也是道比较麻烦的模拟题目,自己如果没有看题解,私自认为还是写不出来的。
因为思想都没有,解决问题的办法也没有。根本就是一片空白,但看了题解,才豁然开朗,原来是这么回事!
其中,很重要的一点就是,将你所需要的题目中给出的事例打成表,然后转换成唯一的数字问题,这样找起来,对应起来就简单多了。
然后就是枚举,说实话,天天看别人枚举,枚举。以为是一种很简单的方法,但其实,枚举是一种很奇怪的思想,是一种计算机独有的思想,你要学会用计算机思考问题,而不是用人的智能化去想问题,那么你永远都做不会枚举的题目。
此题的步骤。找听牌,不如就给他所有种类的牌,然后判断这种状态是不是赢的状态。当然赢的状态很多种,但我们只要能找到一种,那么这张牌就是一张听牌。
要赢,就必须要有唯一的一对将,所以我们首先就要把将的问题解决,如果连将都没有,那肯定是赢不了的。
然后就是一个一个的去三个和顺子。当然这两个是互不影响的。而且在每次去的过程中,都要回溯递归求解。即不成功就恢复原来的数据。
好吧,这样做起来就基本上能作对了,但是,如果不小心,想的不周到,,这道题目还是很难A的。
贴出代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
char mahjong[44][22] = {"1T", "2T", "3T", "4T", "5T", "6T", "7T", "8T", "9T",
"1S", "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S",
"1W", "2W", "3W", "4W", "5W", "6W", "7W", "8W", "9W",
"DONG", "NAN", "XI", "BEI", "ZHONG", "FA", "BAI"};
int mj[22];
int c[44];
int converse(char *s) //将输入的字符串对应到每一种牌的id上
{
for (int i = 0; i < 34; i++)
{
if (strcmp(mahjong[i], s) == 0)
{
return i;
}
}
return -1;
}
bool search(int dep)
{
for (int i = 0; i < 34; i++)
{
if (c[i] >= 3)//找到三个.
{
if (dep == 3) //如果前面的已经满足了三个,那么这个一满足,就可以直接返回true
{
return true;
}
c[i] -= 3;
if (search(dep + 1))//如果不满足,就继续递归调用
{
return true;
}
c[i] += 3;
}
}
for (int i = 0; i <= 24; i++) //开始的时候把找三个的和找顺子的在一起了,明天不可以.找三个是找三个,找顺子是找顺子,
{ //两者丝毫不一样.
if (i % 9 <= 6 && c[i] >= 1 && c[i + 1] >= 1 && c[i + 2] >= 1) // 注意i%9的含义是找到对应一起的顺子然后小于6是为了满足对应一起.
{
if (dep == 3)
{
return true;
}
c[i] -= 1;
c[i + 1] -= 1;
c[i + 2] -= 1;
if (search(dep + 1))
{
return true;
}
c[i] += 1;
c[i + 1] += 1;
c[i + 2] += 1;
}
}
return false;
}
bool check()
{
for (int i = 0; i < 34; i++)
{
if (c[i] >= 2)
{
//这里是不应该处理4个的时候的,四个仍然可以拿两个来当将的;错死我了.
c[i] -= 2;
if (search(0))
{
return true;
}
c[i] += 2;
}
}
return false;
}
int main()
{
char s[100];
int cnt = 1;
while (scanf("%s", s) != EOF)
{
if (s[0] == '0')//处理输入结束
{
break;
}
mj[0] = converse(s);
for (int i = 1; i <= 12; i++)
{
scanf("%s", s);
mj[i] = converse(s);
}
printf("Case %d:", cnt++);
int flag = 0;
for (int i = 0; i < 34; i++)
{
memset(c, 0, sizeof(c)); // 因为每次的处理都把C给弄坏了,所以每一次单独求一下c
for (int j = 0; j < 13; j++)
{
c[mj[j]]++;
}
if (c[i] >= 4)
{
continue;
}
c[i]++;
if (check())
{
printf(" %s", mahjong[i]);//这个处理最后输出结果的方法也不错,因为case 后面又个空格,所以一切的输出都可以这样了.
flag = 1; //自己不用去可以控制格式了.
}
c[i]--;
}
if (flag == 0)
{
printf(" Not ready");
}
printf("\n");
}
// system("pause");
return 0;
}