题意:普通的打麻将规则,三个一样的牌或同种花色三张组成的顺子一共4副,再加一个将(两个一样的),判断此时这幅牌是否听牌(差一步就赢了),如果听牌就按给出的顺序输出能赢的最后一张牌。
题解:先按输出顺序写出一个的数组,然后一一枚举,判断如果加入这张牌是否能赢,判断时用dfs+回溯,先选出将,然后dfs选顺子和三张一样的牌,如果数量能达到4就返回正确,访问结束后,牌数还原。
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
using namespace std;
const int N = 40;
string mah[34] = {"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"};
string in[N], ans[N], str;
int vis[N];
int dfs(int cur) {
if (cur == 4)
return 1;
for (int i = 0; i < 34; i++) {
if (vis[i] >= 3) {
vis[i] -= 3;
if (dfs(cur + 1))
return 1;
vis[i] += 3;
}
if (i < 27 && i % 9 < 7 && vis[i] && vis[i + 1] && vis[i + 2]) {
vis[i]--;
vis[i + 1]--;
vis[i + 2]--;
if (dfs(cur + 1))
return 1;
vis[i]++;
vis[i + 1]++;
vis[i + 2]++;
}
}
return 0;
}
int judge() {
for (int i = 0; i < 14; i++) {
for (int j = 0; j < 34; j++)
if (in[i] == mah[j]) {
vis[j]++;
break;
}
}
for (int i = 0; i < 34; i++)
if (vis[i] == 5)
return 0;
for (int i = 0; i < 34; i++)
if (vis[i] >= 2) {
vis[i] -= 2;
if (dfs(0))
return 1;
vis[i] += 2;
}
return 0;
}
int main() {
int t = 1, n, num;
while (getline(cin, str) && str[0] != '0') {
n = num = 0;
for (int i = 0; i < N; i++)
in[i] = "";
for (int i = 0; i < str.size(); i++) {
while (isalpha(str[i]) || isdigit(str[i])) {
in[n] += str[i];
i++;
}
n++;
}
for (int i = 0; i < 34; i++) {
in[13] = mah[i];
memset(vis, 0, sizeof(vis));
if (judge())
ans[num++] = mah[i];
}
cout << "Case " << t++ << ":";
if (num != 0) {
for (int i = 0; i < num; i++)
cout << " " << ans[i];
cout << endl;
}
else
cout << " Not ready" << endl;
}
return 0;
}