[Coding Test] 균형점 (SWEA: 1245)

균형점 (SWEA: 1245)

이번 문제는 이분탐색 개념을 이용해 값을 근사하는 과정을 다룹니다. 문제에서는 N개의 자성체들이 존재하는 공간에 존재하는 N - 1개의 평형지점을 구해야 합니다.

모든 자성체들은 일직선 상에 존재하는 것을 가정합니다. 따라서 어떠한 물체가 자성체들이 나열된 직선 상에 놓였을 때, 한 개의 자성체와 물체 사이에 작용하는 인력은 다음과 같이 계산됩니다.

$F = G \frac{m_1 * m_2}{d^2} $

이때, 좌표값의 오차가 $10^{-12}$보다 작아야 하는 조건이 존재합니다.

소스코드

#include<iostream>
using namespace std;

struct Magnet {
	int position, weight;
};
int num;
Magnet magnetArr[10];

double bisection(int);

int main(int argc, char** argv) {
	
	// freopen("sample_input.txt", "r", stdin);
	
	int T, test_case;
	cin >> T;

	for (test_case = 1; test_case <= T; test_case++) {
		cin >> num;
		for (int i = 0; i < num; i++) cin >> magnetArr[i].position;
		for (int i = 0; i < num; i++) cin >> magnetArr[i].weight;

		cout.setf(ios::fixed, ios::floatfield);
		cout.precision(10);

		cout << '#' << test_case << ' ';
		for (int i = 0; i < num - 1; i++) {
			cout << bisection(i) << ' ';
		} cout << '\n';
	}

	return 0;
}

double bisection(int i) {
	double mid, low = magnetArr[i].position, high = magnetArr[i + 1].position;

	for (int turn = 0; turn < 100; turn++) {
		double leftforce = 0, rightforce = 0;
		mid = (low + high) / 2.0;

		double d;
		for (int left_idx = 0; left_idx <= i; left_idx++) {
			d = magnetArr[left_idx].position - mid;
			leftforce += (magnetArr[left_idx].weight * magnetArr[i].weight) / (d * d);
		}

		for (int right_idx = i + 1; right_idx <= num; right_idx++) {
			d = magnetArr[right_idx].position - mid;
			rightforce += (magnetArr[right_idx].weight * magnetArr[i].weight) / (d * d);
		}

		if (leftforce < rightforce) high = mid;
		else if (leftforce > rightforce) low = mid;
		else return mid;
	}

	return mid;
}

해당 코드가 허용 오차를 만족한다고 가정하는 이유는 turn 횟수입니다. 한 번의 Loop에 범위는 1/2 로 줄어듭니다. 따라서 어떠한 구간 $L$이 주어졌을 때, $2^{100}$의 정확도로 위치를 파악할 수 있습니다.

또한 printf("%.10f)와 같이 출력 형식자를 지정하는 방법 대신, 아래와 같은 코드가 사용되었습니다.

cout.setf(ios::fixed, ios::floatfield);
cout.precision(10);

Updated:

Leave a comment