Mahjong Hands - NZIC 2023 Round 3 Tutorial
This problem comes from New Zealand Olympiad in Informatics (NZOI) 2023 Round 3. For the problem statement refer to here: Mahjong Hands.
I assume there are several different approaches toward this problem, but in this blog I will just describe my own solution.
1. Algorithm
We input the number of pins, bamboos and characters, and we store these numbers in an array (
nums
).We loop through each type of pins (pins, bamboos or characters).
We input the tiles of this type, and we store these tiles in an array (
tiles
) of size 9. For example, each time we get a tile of 2, we incrementtiles[1]
by 1; each time we get a tile of 5, we incrementtiles[4]
by 1.We check if the tiles are SIMPLE or not.
Then, we loop from 1 to 9:
- We calculate the maximum number of STRAIGHTs we can have.
- We minus the number of STRAIGHTs.
For example, if we have PINS: 1, 2, 3, 1, 2, 3.
Then we would have thetiles
as[2, 2, 2]
.
This means the the maximum of STRAIGHTs we can have is 2.
We minus 2 fromtiles[0]
,tiles[1]
andtiles[2]
.
Hencetiles
becomes[0, 0, 0]
. - We calculate the maximum number of SETs we can have.
- We minus the number of SETs.
This step can be simplified by just doingtiles[i] % 3
. - After the above process, we check if
tiles[i]
is 0 or 2.
If the number of tiles in this SUIT is a multiple of 3, this means that the identical pair is not included in this set. Thus all the tiles contribute to STRAIGHTs or SETs, hence
tiles
should be filled with zeros.
Otherwise, we have the identical pair in this set. This means we have atiles[i]
with 2 tiles, the rest filled with zeros.
Iftiles
meet the above conditions then the set is COMPLETE, otherwise no.Return the state.
I believe the key to this problem is to calculate the STRAIGHTS before the SETS, because 3 tiles with the same number can contribute to a STRAIGHT plus an identical pair.
2. C++ Solution
#include <bits/stdc++.h>
using namespace std;
int main() {
int nums[3];
cin >> nums[0] >> nums[1] >> nums[2];
bool simple = true, complete = true;
int tile;
for (int t = 0; t < 3; t++) {
int tiles[9] = { 0 };
for (int i = 0; i < nums[t]; i++) {
cin >> tile;
tiles[tile - 1] += 1;
}
if (tiles[0] or tiles[8])
simple = false;
int zeros = 0, twos = 0;
for (int i = 0; i < 9; i++) {
if (i < 7) {
int minus = min({tiles[i], tiles[i + 1], tiles[i + 2]});
tiles[i] -= minus, tiles[i + 1] -= minus, tiles[i + 2] -= minus;
}
tiles[i] = tiles[i] % 3;
if (tiles[i] == 0)
zeros++;
else if (tiles[i] == 2)
twos++;
}
if (!(nums[t] % 3 == 0 and zeros == 9 or
nums[t] % 3 == 2 and twos == 1 and zeros == 8))
complete = false;
}
if (simple and complete)
cout << "WIN" << endl;
else if (simple)
cout << "SIMPLE" << endl;
else if (complete)
cout << "COMPLETE" << endl;
else
cout << "SAD";
return 0;
}