C++で指定された遷移を通じて最終地点に到達可能かどうかを判定する方法
x軸上にn個の点があり、点同士の間で許可された遷移(移動)のリストが与えられているとします。この遷移のみを使って、開始地点から最終地点に到達できるかどうかを判定するのが本記事のテーマです。
例えば、点x1と点x2の間に遷移が存在する場合、点xからx1とx2の間の任意の中間点へ移動することも、直接x2へ移動することもできます。
問題の例
n = 5、遷移が「0から2」「2から4」「3から5」の3つである場合を考えてみましょう。このとき、出力は「YES」になります。なぜなら、0→2→3→5 という経路が存在するからです。
アルゴリズムの考え方
この問題を解くための手順は以下の通りです。
- ペアのリストを、各ペアの最初の要素(始点)を基準にソートします。
- リストの2番目のペアから順に、そのペアの始点が「前のペアの終点」と「現在のペアの終点」の間にあるかどうかを確認します。
- この条件により、隣接する2つのペアの間に経路がつながっているかどうかを判定できます。
- 最後に、到達した点が目的地の点であり、開始した点が出発点であるかを確認します。
条件をすべて満たしていれば「YES」を表示し、そうでなければ「NO」を表示します。
実装例(C++コード)
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
bool isPathPairFound(int n, vector<pair<int, int> > array) {
sort(array.begin(), array.end());
int start_point = array[0].first;
int end_point = array[0].second;
for (int i = 1; i < n; i++) {
if (array[i].first > end_point)
break;
end_point = max(end_point, array[i].second);
}
return (n <= end_point && start_point == 0);
}
int main() {
vector<pair<int, int> > array;
array.push_back(make_pair(0, 2));
array.push_back(make_pair(2, 4));
array.push_back(make_pair(3, 5));
if (isPathPairFound(5, array))
cout << "Path has found";
else
cout << "NO Path has found";
}出力結果
Path has found
コードの解説
このコードでは、まずsort関数を使ってペアのリストを始点の昇順に並べ替えています。その後、変数end_pointを更新しながら各ペアを順に走査し、現在のペアの始点がこれまでに到達可能な範囲を超えていないかをチェックします。範囲が途切れていればループを抜け、最終的にend_pointが目的地n以上であり、かつ始点が0であるかどうかを返します。
このアルゴリズムの計算量は、ソートにO(n log n)、走査にO(n)かかるため、全体としてO(n log n)となります。点の数が多い場合でも効率的に動作する実用的なアプローチです。
-
C++でグリッド内の指定方向に実行可能な移動回数をカウントする方法
サイズ n × m のグリッドと、開始座標 (x, y) を表す変数が与えられます。さらに、グリッド内を移動するために使用できるステップのペア(例:(1,1)、(2,2) など)も与えられます。各ペアは、x 軸と y 軸方向に進む単位移動量を表します。ゴールは、境界 [1, n] × [1, m] の範囲内でグリッド内を移動できる合計ステップ数を求めることです。 たとえば、n = 5、m = 4、現在位置が (2, 2)、選択したステップが (1, -1) の場合を考えてみましょう。このステップを 1 回適用すると (3, 1) に移動できますが、もう 1 回適用すると (4, -1) となり
-
C++で配列要素の階乗の最大公約数(GCD)を求める方法
N個の要素を持つ配列Aが与えられたとき、配列内のすべての要素の階乗の最大公約数(GCD)を求めることを考えます。例えば、配列の要素が {3, 4, 8, 6} の場合、各要素の階乗は 3! = 6、4! = 24、8! = 40320、6! = 720 となり、これらのGCDは 6 になります。解法のポイントここで重要な数学的な性質があります。2つの数のGCDとは、両方の数を割り切る最大の数のことです。階乗の場合、小さい数の階乗は必ず大きい数の階乗を割り切ることができます。つまり、2つの階乗のGCDは、小さい方の数の階乗そのものになります。例えば、3! と 5! のGCDを考えると、3! =