最小・最大除去ゲームで最後に残る数を求めるC++コードの解説
問題概要
n個の要素からなる配列Aがあり、ボード上にn個の数値が書かれているとします。AmalとBimalが交互にターン制のゲームを行います。各ターンで、プレイヤーは数値を1つ選んでボードから取り除きます。Amalが先手です。Amalは最後にボードへ残る数をできるだけ小さくしたいと考え、一方のBimalはそれをできるだけ大きくしたいと考えています。このとき、最終的にボードに残る数を求めましょう。
例えば、入力が A = [2, 1, 3] の場合、出力は 2 になります。これは、Amalが先に 3 を取り除き、次にBimalが 1 を取り除くため、最後に残る数が 2 になるからです。
解法のアプローチ
この問題を解くためには、以下の手順に従います。
- n を配列 A のサイズとします。
- 配列 A を昇順にソートします。
- A[(n − 1) / 2](切り捨て除算)を返します。
なぜ中央値が答えになるのか
両者が最適な戦略を取るとき、最後に残る数は配列の中央値になります。ソート後の配列では、Amalは大きい側の要素から順に取り除こうとし、Bimalは小さい側の要素から順に取り除こうとします。両者の行動が互いに打ち消し合う結果、ちょうど中央の位置にある要素が最後まで残るのです。
C++での実装例
理解を深めるために、以下の実装を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
int solve(vector<int> A){
int n = A.size();
sort(A.begin(), A.end());
return A[(n - 1) / 2];
}
int main(){
vector<int> A = { 2, 1, 3 };
cout << solve(A) << endl;
}
入力
{ 2, 1, 3 }
出力
2
計算量
このアルゴリズムの時間計算量は O(n log n)(ソートにかかるコスト)、空間計算量は O(1) となります。非常にシンプルでありながら、ゲーム理論におけるミニマックス戦略の性質を利用した効率的な解法です。
-
C++でN回の操作後に存在する正三角形の数を求める方法
この記事では、色付きの三角形を描き、その中に存在する正三角形の数を求める方法を解説します。まず無色の三角形を用意し、それを4つの同じ面積を持つ小さな正三角形に分割します。この操作をn回繰り返し、最終的な図形の中にいくつの正三角形が存在するかを求めます。解決策へのアプローチこの問題を解くには、主に2つのアプローチがあります。総当たり(ブルートフォース)アプローチ観察すると、各ステップごとに三角形の数は「3 × 前回の数 + 2」という規則で増加していくことがわかります。したがって、n回ループを回すことで三角形の数を順次計算できます。コード例#include <iostream> us
-
C++で数のPoliteness(礼儀正しさ)を求める方法【素因数分解で効率化】
この記事では、正の整数Nが与えられたときに、その数の「Politeness(礼儀正しさ)」をC++で求める方法を解説します。 Polite Number(礼儀正しい数)とは? Polite Numberとは、2つ以上の連続する整数の和として表すことができる数のことです。 数のPolitenessは、その数を連続する整数の和で表現できる方法の総数として定義されます。 例で問題を理解する 入力: n = 5 出力: 1 説明:2 + 3 = 5 が唯一の連続する整数の和であり、これ以外の表し方は存在しないため、答えは1になります。 解法アプローチ 1. シンプルな解法(全探索) 最も単純なアプロー