题面(The Problem):
题面简直长的要死,一看就是大模拟,队里可能就我打过麻将,我直接拿来读了,比赛的时候看了我好久。
题目大概意思(Meaning of the problem):
给你一手14张的手牌,判断打掉打哪一张听牌并且输出对应的听的牌,如果已经胡了的话直接输出Tasumo
众所周知(bushi)麻将胡牌要一对雀头(指的是两张一样的牌)剩下来要全部是碰(三个相同)或者吃(三个按照顺序的牌)(其实是中间没有杠或者碰或者吃之判断手牌)
思路(Methods):
大模拟首先要思考好枚举方法。
1.先枚举打掉的牌,共14次2.枚举抽到的的牌,共14种
3.枚举雀头,有雀头继续向下判断,无雀头肯定无法胡牌,并将雀头从排牌堆中去掉
4.DFS,枚举所有顺子和碰子(3个相同)每次操作均删除掉临时结构体中相应的牌,最后判断牌堆是否为空,为空则加入输出队列。
代码(Code):
#include "bits/stdc++.h"
#define endl "\n"
using namespace std;
map<char, int>mjNum;
char _mjName[] = "wbsz";
struct tiles {
int num[10], backup[10];
char type;
void back() {
for (int i = 0; i < 10; ++i) {
backup[i] = num[i];
}
return;
}
void renew() {
for (int i = 0; i < 10; ++i) {
num[i] = backup[i];
}
return;
}
void output() {
for (int i = 0; i < 10; ++i) {
if (num[i]) {
cout << "there are " << num[i] << " " << i << type << endl;
}
}
return;
}
void init(char ch) {
memset(num, 0, sizeof(num));
type = ch;
return;
}
bool check_zi() {
//cout << "++++check zi+++++" << endl;output();
for(int i = 1; i <= 7; ++i) {
//cout << "check_zi find in " << i << " with num " << num[i] << endl;
if (num[i] % 3 != 0) {
//cout << "check zi break in " << i << type << " with the value of " << num[i] << endl;
return false;
}
}
//cout << "check_zi is Success" <<endl;
return true;
}
bool check3() {
for (int i = 1; i <= 9; ++i) {
if (num[i]) {
if (num[i] >= 3) {
//cout << i << type << " hase delete in size of 3" << endl;
tiles temp = *this;
temp.num[i] -= 3;
if (temp.check3()) return true;
}
if (i + 2 <= 9 && num[i + 1] > 0 && num[i + 2] > 0) {
tiles temp = *this;
temp.num[i + 1]--, temp.num[i]--,temp.num[i + 2]--;
if (temp.check3()) return true;
}
return false;
}
}
return true;
}
// bool check3() {
// back();
// //cout << "====bef renew=====" << endl;output();
// bool checkrsl = check3_in();
// renew();
// //cout << "====after renew====" << endl;output();
// return checkrsl;
// }
};
struct outputRow {
pair<char, int>type;
vector<pair<char, int>>addTail;
void init() {
type.first = 'a';
addTail.clear();
return;
}
void printAline() {
cout << type.second << type.first << ' ';
for (auto it : addTail) {
cout << it.second << it.first;
}
cout << endl;
return;
}
};
struct table {
tiles mj[4];
//tiles mjBackup[4];
vector<outputRow>expert;
outputRow outputRowTemp;
void init() {
expert.clear();
outputRowTemp.init();
for (int i = 0; i < 4; ++i) {
mj[i].init(_mjName[i]);
//mjBackup[i] = mj[i];
}
return;
}
// void renew() {
// for (int i = 0; i < 4; ++i) {
// mj[i] = mjBackup[i];
// }
// }
bool check3() {
for (int i = 0; i < 3; ++i) {
if (!mj[i].check3()) {
//cout << "check3 break in " << _mjName[i] << endl;
return false;
}
}
//cout << "check in 3 in table's check3 function is Success" << endl;
if (!mj[3].check_zi()) return false;
//cout << "check in zi in table's check3 function is Success" << endl;
return true;
}
bool check() {
bool have2 = false;
for (int i = 0; i < 4; ++i) {
for (int j = 1; j < 10; ++j) {
if (i == 3 && j == 8) break;
if (mj[i].num[j] >= 2) {
table temp = *this;
temp.mj[i].num[j] -= 2;
if (temp.check3()) return true;
}
}
}
return have2;
}
bool getTail() {
for (int i = 0; i < 4; ++i) {
for (int j = 1; j <= 9; ++j) {
if (i == 3 && j == 8) break;
mj[i].num[j]++;
//cout << "====add tile in " << j << _mjName[i] << "=======" << endl;
if(check()) {
//cout << "outputrow was pushed in " << i << ',' << j << endl;
outputRowTemp.addTail.emplace_back(_mjName[i], j);
}
mj[i].num[j]--;
}
}
return true;
}
void printSteps() {
cout << expert.size() << endl;
for (auto it : expert) {
it.printAline();
}
return;
}
void find() {
// for (int i = 0; i < 4; ++i) {
// mjBackup[i] = mj[i];
// }
if (check()) {
cout << "Tsumo!\n";
return;
}
for (int i = 0; i < 4; ++i) {
for (int j = 1; j <= 9; ++j) {
if (mj[i].num[j]) {
mj[i].num[j]--;
outputRowTemp.init();
//cout << "===del " << j << _mjName[i] << " to get tails====" << endl;
//cout << "purchase with" << j << _mjName[i] << endl;
getTail();
if (!outputRowTemp.addTail.empty()) {
//cout << "expert was pushed in " << i << j << endl;
outputRowTemp.type = {_mjName[i], j};
expert.push_back(outputRowTemp);
}
mj[i].num[j]++;
}
}
}
printSteps();
return;
}
};
int main(void) {
int t;
for (int i = 0; i < 4; ++i) {
mjNum[_mjName[i]] = i;
}
cin >> t;
while (t--) {
table play;
string str;
cin >> str;
play.init();
for (int i = 0; i < 28; i += 2) {
string now = str.substr(i, 2);
play.mj[mjNum[now[1]]].num[now[0] - '0']++;
}
//cout << "input test :" << endl;for (int i = 0; i < 4; ++i) play.mj[i].output();
play.find();
}
return 0;
}