알고리즘/문제풀이

백준 13433 기하 문제

마빈스펙트럼 2021. 7. 14. 05:40

https://www.acmicpc.net/problem/13433

 

13433번: 기하 문제

첫째 줄에 가장 왼쪽 원과 직선이 닿는 점과 가장 오른쪽 원과 직선이 닿는 점 사이의 거리의 최솟값을 출력한다. 정답과의 절대/상대 오차는 10-9까지 허용한다.

www.acmicpc.net

풀이 

더보기

두 개의 원이 접해있다면 다음과 같은 그림처럼 표현됩니다.

원의 중심 사이에는 다음과 같은 삼각형이 생길 것이고 

 

피타고라스를 이용한다면 삼각형의 세 개의 변을 구할 수 있습니다.

 

 

 삼각형에서 나온 값을 토대로 다음 원의 중심 좌표를 알 수 있습니다.

 

 

이제 우리에게 주어진 문제는 원을 어떤 순서로 배치해야 가장왼쪽점과 가장오른쪽점의 거리가 가장 짧은지인데...

 

다행히 문제에서 나오는 원의 개수는 N (3 ≤ N ≤ 8)이기 때문에

8! = 40,320의 경우의 수로 배치를 해볼 수 있습니다.

저는 next_permutation을 사용해서 모든 배치의 경우의 수를 탐색하도록 구현했습니다.

 

 

 

 

 

한 가지 주의해야 할 점이 있습니다!!

 

 

다음 그림과 같이 원이 이전에 설치된 원이 아닌 다른 원에 접하는 경우가 생길 수가 있기 때문에

다른 원과 접하는 경우도 고려해서 원의 중심을 구해야됩니다.

 

 

코드

더보기
#include <bits/stdc++.h>

using namespace std;

#define endl "\n"
#define int long long
#define float double

using namespace std;

int32_t main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    cout << fixed;
    cout.precision(10);

    vector<float> arr;
    vector<float> r;
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
        arr.push_back(i);
    for (int i = 0; i < n; i++)
    {
        float a;
        cin >> a;
        r.push_back(a);
    }

    float ans = 1000000000000;

    do
    {
        vector<float> P;
        P.push_back(0);

        for (int i = 1; i < n; i++)
        {
            float nextR = r[arr[i]];
            float tempP = P[0];
            for (int j = 0; j < P.size(); j++)
            {
                float nowR = r[arr[j]];
                float addX = 2 * sqrt(nowR * nextR);

                tempP = max(tempP,P[j]+ addX);
            }

            P.push_back(tempP);
        }

        ans = min(P.back(), ans);
    }
    while (next_permutation(arr.begin(), arr.end()));

    cout << ans << endl;
}

 

-----------------------------------------------------------------------------------------------------------------------------------

질문은 언제나 환영합니다.