【C++】線分の中心を移動させて実現できる最大の交差領域を求める方法
はじめに
このチュートリアルでは、線分の中心を移動させることで実現できる最大の交差領域を求めるC++プログラムについて解説します。
この問題では、3つの線分の中心座標とそれぞれの長さが与えられます。各線分の中心は距離Kまで移動することが許されており、その移動を活用して交差領域の長さを最大化することが目的です。
アルゴリズムの考え方
まず、3つの中心座標を昇順にソートし、最も外側にある2つの中心(最小値と最大値)の距離に着目します。この距離と移動量K・線分の長さとの関係から、次の3つの場合に分けて判定できます。
- 中心間の距離 ≥ 2K + 線分の長さ の場合:どれだけ移動しても交差は発生しないため、0を返します。
- 中心間の距離 ≥ 2K の場合:移動によって部分的な交差を作ることができるため、「2K −(中心間の距離 − 線分の長さ)」を返します。
- 上記以外の場合:すでに線分全体が交差している状態のため、線分の長さをそのまま返します。
サンプルコード
#include <bits/stdc++.h>
using namespace std;
// 最大交差を求める関数
int max_intersection(int* center, int length, int k) {
sort(center, center + 3);
if (center[2] - center[0] >= 2 * k + length) {
return 0;
}
else if (center[2] - center[0] >= 2 * k) {
return (2 * k - (center[2] - center[0] - length));
}
else
return length;
}
int main() {
int center[3] = { 1, 2, 3 };
int L = 1;
int K = 1;
cout << max_intersection(center, L, K);
}
出力結果
1
コードの解説
この例では、中心座標 {1, 2, 3} を持つ3つの線分が与えられ、それぞれの長さは L = 1、移動量の上限は K = 1 です。
ソート後、最も外側の中心同士の距離は 3 − 1 = 2 となります。この値は「2K + 長さ = 3」より小さいため交差は不可能ではなく、また「2K = 2」以上であるため部分的な交差が可能です。したがって、計算式「2 × 1 −(2 − 1)= 1」により、最大交差の長さとして 1 が出力されます。
このように、外側の2つの中心の距離に着目するだけで、中央の線分の位置に関係なく答えを効率的に求めることができます。計算量はソート部分が支配的となり、O(N log N)(ここでは要素数3なのでほぼ定数時間)で処理できます。
-
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) = (