NC220392. Riichi!!
描述
Yui is a cute girl expert in a kind of game. In case you are not familiar with the game, here we briefly introduce its rules.
is played with , divided into 34 . To simplify the problem, we assume that (although in real-world game one kind usually contains up to 4 tiles). The 34 kinds of tiles can be further divided into 4 , named as , and . The have 9 kinds for each suite and tiles has only 7 kinds.
Here are the all 34 kinds of tiles used in game: Each row refers to a suite of tiles --- in order.
Minor differences exist in various versions of game, and here we only consider some basic rules.
During the game, each player holds 13 tiles in hand. For each round, one player would draw one tile from the Mahjong table, then discard one tile from one of the 14 tiles owned at the time. A player wins the game if in a round he can create a (defined below) with the 13 tiles in hand and 1 tiles drawn from table or discarded from other player.
A consists of 14 tiles, which can be divided into four \texttt{kezi} or , and an additional .
Here, is a set of 3 identical tiles:
Finally, is a pair of identical tiles:
Here are some samples of special combinations:
If the player can obtain a special combination by getting some tile, then we call the player is in the status. In this status one can achieve victory once he/she gets the desired kind of tile!
For example, the following sets of 13 tiles are in the status, the tiles after the space indicates the desired tiles to achieve victory.
Now Yui is playing the game. Sometimes she is very close to victory that if she tosses some tile she would reach the status, while sometimes such tiles does not yet exist. And sometimes she has already got a winning hand of 14 tiles!
To help you improve your skills, Yui decides to give you a test. Now it is Yui's turn and she has 14 tiles in her hand. Please tell her which tile should be discarded in order to reach status, or just tell her that she has already won in this round!
输入描述
The input contains multiple tests cases. The first line includes a single integer --- the number of test cases. It is guaranteed that .
Each of the next lines indicates a test case. It contains a string of 28 characters, describing the 14 tiles that Yui currently has. For every , the -th tile obtained by Yui is described by the -th and -th characters in the string: the former is a digit denoting the rank of the tile in its suite and the latter is one of \texttt{w, b, s, z}, which means the suite and respectively. It is guaranteed that all the in the input are valid and legal.
输出描述
Output the answer for each test case separately. For each test case, if Yui has already reach the winning status in this round, output in a single line.
Otherwise, output a single integer in a single line, the number of choices for discarding tiles to reach status.
Each of the next lines should indicate one way to reach the status. It should start with two characters indicating the tile to be discarded. To prove that such way leads to a status, you should print all the tiles that can lead to victory for the status. For clarity, print a space between the first two characters and the rest of the line.
Pay attention to the order when printing the desired tiles, as there is NO special judge. For tiles in different suites, print them in the order (that is, always print tiles at first, and so on). For tiles in the same suite, print the cards in the ascending order of their digits (that is, the tile with smaller number goes first). Additionally, if there are several tiles available for a status to achieve victory, you should also sort them in the same way. See the Sample Output for details.
示例1
输入:
5 1w2w3w4b5b6b7s8s9s1b1b1z2z6z 1w2w3w4b5b6b7s8s9s1b1b2z2z6z 1w2w3w4b5b6b7s8s9s1b1b2z2z2z 1b2b3b4b5b6b2s4s5s5s5s6s7s8s 1b1b1b2b3b4b5b6b7b8b9b9b9b1s
输出:
0 1 6z 1b2z Tsumo! 4 2s 3s4s6s9s 4s 2s 5s 3s 8s 3s 4 2b 1s 5b 1s 8b 1s 1s 1b2b3b4b5b6b7b8b9b
C++(g++ 7.5.0) 解法, 执行用时: 483ms, 内存消耗: 652K, 提交时间: 2022-10-08 21:12:58
#pragma GCC optimize(2) #include<bits/stdc++.h> #define endl '\n' using namespace std; using ll=long long; int id(char x){ if(x=='w')return 0; if(x=='b')return 1; if(x=='s')return 2; return 3; } int a[34]; void init(){ memset(a,0,sizeof a); string str;cin>>str; for(int i=0;i<28;i+=2){ int x=str[i]-'0'; ++a[x-1+9*id(str[i+1])]; } } int ta[34]; int check(){ memcpy(ta,a,sizeof ta); for(int i=27;i<34;++i) if(ta[i]%3)return 0; for(int i=0;i<27;++i){ ta[i]%=3; if(ta[i]){ if(i%9>6)return 0; int mi=min(ta[i],min(ta[i+1],ta[i+2])); if(ta[i]>mi)return 0; ta[i]-=mi,ta[i+1]-=mi,ta[i+2]-=mi; } } return 1; } int win(){ for(int i=0;i<34;++i){ if(a[i]>=2){ a[i]-=2; int f=check(); a[i]+=2; if(f)return 1; } } return 0; } vector<int>ans[34]; string change(int x){ int y=x/9; x%=9; return string(1,x+1+'0')+"wbsz"[y]; } signed main() { ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int T;cin>>T; while(T--){ init(); if(win()){ cout<<"Tsumo!\n"; continue; } int cnt=0; for(int i=0;i<34;++i){ ans[i].clear(); if(!a[i])continue; --a[i]; for(int j=0;j<34;++j){ if(i==j)continue; ++a[j]; if(win())ans[i].push_back(j); --a[j]; } ++a[i]; if(!ans[i].empty())++cnt; } cout<<cnt<<endl; for(int i=0;i<34;++i){ if(ans[i].empty())continue; cout<<change(i)<<' '; for(auto it:ans[i])cout<<change(it); cout<<endl; } } return 0; } // init? // var->0? // infinite dfs? // out of bound? // max_element / min_element?
C++(clang++11) 解法, 执行用时: 306ms, 内存消耗: 896K, 提交时间: 2021-04-19 11:51:22
#include<vector> #include<cstdio> #include<algorithm> #define rep(i,l,r) for (int i=(l); i<=(r); i++) using namespace std; int T,a[34]; char s[23]; bool he2(int b[]){ rep(i,0,33) a[i]=b[i]; rep(i,0,26) if (a[i]%3){ if (i%9>6) return 0; a[i]=a[i]%3; if (a[i]>a[i+1]||a[i]>a[i+2]) return 0; a[i+1]-=a[i]; a[i+2]-=a[i]; a[i]=0; } rep(i,27,33) if(a[i]%3) return 0; return 1; } bool he(int b[]){ int a[34]; rep(i,0,33) a[i]=b[i]; rep(i,0,33) if(a[i]>=2){ a[i]-=2; if (he2(a)) return 1; a[i]+=2; } return 0; } char gett(int x){ if(x==0) return 'w'; else if(x==1) return 'b'; else if(x==2) return 's'; else return 'z'; } int main(){ for (scanf("%d",&T); T--; ){ scanf("%s",s); int cnt=0,x[37]={0}; vector<int> ans[37]; rep(i,0,13){ if(s[i*2+1]=='w') x[s[i*2]-'1']++; else if(s[i*2+1]=='b') x[s[i*2]-'1'+9]++; else if(s[i*2+1]=='s') x[s[i*2]-'1'+18]++; else x[s[i*2]-'1'+27]++; } if(he(x)) printf("Tsumo!\n"); else{ rep(i,0,33) if(x[i]){ rep(j,0,33){ x[i]--; x[j]++; if(he(x)) ans[i].push_back(j); x[j]--; x[i]++; } if(ans[i].size()) cnt++; } printf("%d\n",cnt); rep(i,0,33) if(ans[i].size()){ printf("%d%c ",i%9+1,gett(i/9)); for (int j=0; (int)j<ans[i].size(); j++) printf("%d%c",ans[i][j]%9+1,gett(ans[i][j]/9)); puts(""); } } } return 0; }