ほぼ静的な計画法

競技プログラミングで解いた問題の解法とコードを晒していくページ。ややマイナーなC♯。

AOJ 0043 (Puzzle : パズル)

【問題】

https://onlinejudge.u-aizu.ac.jp/problems/0043

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0043

【解説】

「パズル」という名前の問題であるが、平たくいうと一色からなる麻雀あがり判定(特殊役除く)である。麻雀を知らない人でも問題文から解くことができるが、以下用語として麻雀用語を使用した方が簡潔なので、麻雀のあがりに関するwikipediaのリンクを貼っておく。

入力として13枚の牌が与えられるので、それに1~9の数値を加えた14枚が4面子1雀頭になっているかを判定すればよい。

判定の順序については、「牌の枚数の確認」⇒「雀頭の確定」⇒「順子の取り出し」⇒「刻子の取り出し」の順に処理をしていった。

まずは、牌の枚数確認だが、そもそも1つの牌の枚数が4を超える場合はNGとして判定する。

次に、雀頭の確定であるが、牌の合計値から雀頭の候補を絞りこむことができる。面子は、連続した3つの数値、または同一の3つの数値であるため、3で割り切ることができる。よって、牌の合計値を3で割った余りによって、雀頭となりうる数が{1,4,7}、{2,5,8}、{3,6,9}のいずれかに絞りこむことができる。そのため、最大3つの雀頭候補について2枚以上あるかどうかを調べ、2枚以上ある場合に、残りの12枚で面子ができるかを調べればよい。

次に順子の確定であるが、一つの牌の枚数が3枚以外の場合、その3枚以外の牌は必ず順子の一部とならなくてはならない。よって、値の昇順に、3枚以外の牌の数(牌の数を3で割った余り)の分だけ、値、値+1、値+2の牌の枚数を取り去っていけばよい。

最後に残った牌の数が、各値について0または3であれば刻子とすることができるため、そのような場合はOKとして返せばよい。

以下、麻雀の役判定のサイトを参考とした。

【コード】