swexpert
[swexpert] 1245. 균형점 (c++, 이분탐색)
해랑쓰
2021. 9. 29. 17:42
728x90
반응형
n개의 자성체들 사이에는 n-1개의 균형점이 무조건 존재한다고 보고 양 자성체들을 각각 s,e로 놓고
균형점(mid)의 위치를 이분탐색으로 찾아나간다.
오차범위가 무슨 말인지 못하다가 대략 이해했는데
만약 이분탐색으로 양쪽의 힘이 딱 같은 곳을 못발견한채로 s>e가 되어버리는 순간이 있다면
균형점 mid를 찾아야되는데 범위를 넘어가버린다는 것은 이분탐색으로 정확히는 모르지만 s와 e사이에 균형점이 있기는 있다는 것이다. 그럼 세부 좌표 오차일 것이므로 해당 mid를 출력해버리면 된다.
s에 1e^12를 빼거나 e에서 뺐을 때 범위를 넘어가면 두 좌표 사이의 거리는 그것보다 작은 것이니까 그 사이에 무조건 있다. 그래도 mid를 출력해도 되는 이유는 10자리까지만 출력하기 때문인 것 같다.
#include <iostream>
#include <string>
using namespace std;
int t;
double pos[12];
double w[12];
int main(void) {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout << fixed;
cout.precision(10);
cin >> t;
for (int tc = 1; tc<=t ; tc++)
{
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> pos[i]; //좌표
}
for (int i = 0; i < n; i++) {
cin >> w[i]; // 질량값
}
cout << "#" << tc << " ";
double s = 0, e = 0;
for (int i = 0; i < n; i++) {
s = pos[i];
e = pos[i + 1];
while (s <= e) {
double mid = (s + e) / 2;// 둘 사이 거리
double left = 0, right = 0;
for (int i = 0; i < n; i++) {
double diff = mid - pos[i];
double weight = w[i];
if (mid > pos[i])left += (weight / (diff*diff));
else right += (weight / (diff*diff));
}
if (left > right) {//왼쪽 힘이 더 셈
s = mid + 0.000000000001;
if (s > e) {//범위 넘어감
cout << mid << " ";
break;
}
}else if (left < right) {//오른쪽 힘이 더 셈
e = mid - 0.000000000001;
if (s > e) {
cout << mid << " ";
break;
}
}
else {// 같은 곳 찾음
cout << mid << " ";
break;
}
}
}
cout<<"\n";
}
return 0;
}
728x90
반응형