C++で直線の方程式を満たす順序付き点ペアの数を求める方法
問題の概要
本記事では、直線の方程式 y = mx + c を満たす順序付き点ペアの数を求める問題を解説します。配列と、傾き m、切片 c が与えられたとき、配列の要素から選んだ順序付きペア(i, j)のうち、arr[j] = m × arr[i] + c を満たすものの個数を数えます。まずは具体例を見てみましょう。
入力例
arr = [1, 2, 3] m = 1 c = 1
出力例
2
この例では、直線 y = x + 1 上に乗る点のペアとして (1, 2) と (2, 3) の2組が該当します。
アルゴリズム
考え方はシンプルで、取り得るすべてのペアを総当たり(ブルートフォース)で調べる方法です。手順は以下の通りです。
- 配列、m、c を初期化します。
- 二重ループを使って、配列から作れるすべての順序付きペア(i, j)を列挙します。
- 各ペアについて、直線の方程式を満たすかどうかを判定します。
- 判定は、値を方程式に代入して
arr[j] == m * arr[i] + cが成り立つかを確認するだけです。 - 方程式を満たすペアであれば、カウントを1増やします。
- 最終的なカウントを結果として返します。
すべてのペアを調べるため、計算量は O(n²) となります。
C++での実装
上記のアルゴリズムをC++で実装したコードが次の通りです。
#include <bits/stdc++.h>
using namespace std;
bool isSatisfyingLineEquation(int arr[], int i, int j, int m, int c) {
if (i == j) {
return false;
}
return arr[j] == m * arr[i] + c;
}
int getOrderedPointsPairCount(int arr[], int n, int m, int c) {
int count = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (isSatisfyingLineEquation(arr, i, j, m, c)) {
count++;
}
}
}
return count;
}
int main() {
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int n = 10;
int m = 1, c = 1;
cout << getOrderedPointsPairCount(arr, n, m, c) << endl;
return 0;
}実行結果
このコードを実行すると、次の出力が得られます。
9
配列が 1 から 10 までの連続する整数の場合、y = x + 1 を満たすペアは (1, 2)、(2, 3)、…、(9, 10) の9組になるため、正しく 9 が出力されます。
-
C++で点集合の線対称(ラインリフレクション)を判定するアルゴリズム
問題概要2次元平面上にn個の点が与えられます。このとき、y軸に平行な直線で全ての点を鏡映(反射)した結果が、元の点集合と完全に一致するような直線が存在するかどうかを判定します。言い換えれば、ある直線を対称軸として全ての点を反転させたとき、反転後の点の集合が元の集合と同一になるかを確認する問題です。例えば、入力が points = [[1,1],[-1,1]] の場合を考えてみましょう。この場合、x = 0 の直線(y軸)を対称軸とすると、点 (1,1) は (-1,1) へ、(-1,1) は (1,1) へと移ります。点集合全体としては変化がないため、出力は true となります。解法のポイン
-
C++で同一直線上に存在する最大点数を求めるアルゴリズム
問題概要 2次元平面上に複数の点が与えられたとき、同じ直線上に存在する点の最大数を求めるのがこの問題の目的です。 例えば、下図のような6つの点が与えられた場合、最も多くの点が乗っている直線上には4つの点が存在します。 解法のアプローチ この問題は、隣り合う2点を通る直線を基準にして、残りのすべての点がその直線上に乗っているかどうかを順番に判定していくことで解けます。 3点 (x1, y1)、(x2, y2)、(x3, y3) が同一直線上にあるかどうかは、「傾きが等しい」こと、すなわち外積(クロス積)が0になることを利用して判定できます。 (y3 − y2) × (x2 − x1) = (