C++で解く!2人のプレイヤーがサイコロを振るゲームの勝ち・引き分け・負けのパターンを数える方法
問題概要
2つの整数 a と b が与えられたとします。アマル(Amal)とビマル(Bimal)があるゲームを行います。まず、二人はそれぞれ 1 から 6 までの整数を紙に書きます。その後、サイコロを1回振ります。書いた数字がサイコロの出目に最も近いプレイヤーがそのラウンドに勝利し、二人の差が同じであれば引き分けとなります。アマルが a を、ビマルが b を書いたとき、「アマルが勝つ出目の数」「引き分けになる出目の数」「ビマルが勝つ出目の数」をそれぞれ求めてください。
たとえば、入力が a = 2、b = 4 の場合、出力は [2, 1, 3] となります。これはアマルが2通りの出目で勝利できることを示しています。また、サイコロが 3 の目を出した場合は引き分けになります。
解法の考え方
この問題を解く鍵となるのは、2つの数字の「中間値」です。サイコロの出目が (a + b) / 2 より大きいか小さいかによって、どちらのプレイヤーの数字が出目に近くなるかが決まります。
- a と b が等しい場合:すべての出目(6通り)で差が同じになるため、必ず引き分けとなります。
- (a + b) が偶数の場合:中間値が整数になるため、その出目のときにのみ引き分けが1回発生します。
- ビマルの勝ち数:残りの出目すべてが該当するため、「6 − アマルの勝ち数 − 引き分け数」で計算できます。
アルゴリズムのステップ
この問題を解くために、以下の手順に従います。
s1 := 0
s2 := 0
s3 := 0
(a + b) mod 2 が 0 の場合:
s2 := 1
a と b が等しい場合:
s2 := 6
a > b の場合:
s1 := 6 - ((a + b) / 2)
それ以外の場合:
s1 := (a + b - s2 - 1) / 2
s3 := 6 - s1 - s2
s1、s2、s3 を出力する
実装例
理解を深めるため、以下の実装例を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
void solve(int a, int b) {
int s1 = 0, s2 = 0, s3 = 0;
if ((a + b) % 2 == 0)
s2 = 1;
if (a == b)
s2 = 6;
else if (a > b)
s1 = 6 - ((a + b) / 2);
else
s1 = (a + b - s2 - 1) / 2;
s3 = 6 - s1 - s2;
cout << s1 << ", " << s2 << ", " << s3 << endl;
}
int main() {
int a = 2;
int b = 4;
solve(a, b);
}
入力
2, 4
出力
2, 1, 3
まとめ
このように、中間値を利用したシンプルな条件分岐だけで、6通りの出目それぞれについて勝敗を判定できます。すべてのパターンを実際にシミュレーションする必要がなく、O(1) の定数時間で答えを導き出せる点が、このアルゴリズムの大きな魅力です。
-
サイズ d の正十二角形を作れる組み合わせの数を求める C++ プログラム
問題概要 整数 d が与えられたとします。ここで、一辺の長さが 1 の正方形タイルと正三角形タイルが無限枚あるものと考えます。これらのタイルを組み合わせて、一辺の長さが d の正十二角形(12 辺形)を作るとき、その作り方が何通りあるかを求めるのがこの問題です。答えが非常に大きくなる場合は、998244353 で割った余りを返します。 アプローチ この問題は、二項係数を利用することで効率的に解くことができます。結論から言うと、求めるべき答えは C(2d−1, d−1)、すなわち「2d−1 個の中から d−1 個を選ぶ組み合わせの総数」です。 階乗を直接計算すると値が急激に大きくなりオーバー
-
Pythonで二分木を2つの木に分割できるパターン数を数えるプログラム
問題の概要値「0」「1」「2」を含む二分木があるとします。根(ルート)には、少なくとも1つの「0」ノードと1つの「1」ノードが存在しています。ここで、「木の辺(エッジ)を1本削除すると、木が2つの異なる木に分割される」という操作を考えます。このとき、削除後に生成される2つの木のどちらにも「0」と「1」のノードが同時に含まれないように、辺を1本削除する方法が何通りあるかを求めるのがこの問題です。入力例例えば、次のような二分木が与えられたとします。この場合、出力は 1 となります。「0」から「2」へ向かう辺だけが、条件を満たす唯一の削除対象だからです。解法のアプローチこの問題は、DFS(深さ優先探