Software ExpertAcademy의 하나로(1251) 문제이다.


[ 문제풀이 ]

1) 주어진 해저터널을 연결하는데, 이 때 환경 부담금을 최소로 하여 지불할 수 있도록 해저터널을 만들어야 하는 문제이다.

   즉, Minimal Spanning Tree를 만들어야 하는 문제이다.

   MST를 만들기 위해서 크루스칼 알고리즘으로 문제를 접근한다면 쉽게 해결할 수 있다.

   크루스칼 알고리즘에 대해서 잘 모른다면 아래의 링크를 타고 글을 읽고 오자 !

   [ 크루스칼 알고리즘에 대해서 알아보기(Click) ]


  본격적으로 문제를 풀어보자. 크루스칼 알고리즘을 써먹기 위해서는 먼저 가중치들을 모두 구한 후, 그 가중치들을 오름차순으로

  정렬을 해줘야 한다.

  그렇다면, 먼저 가중치를 구하는 법부터 알아보자. 이 문제에서 가중치는 '환경부담금'이 될 것이다.

  환경부담금은 문제에서 "환경부담세율과 각 해저터널 길이의 제곱의 곱"이라고 하였다.

  A(0, 100) 과 B(0, 0), 환경부담세율 E = 1 이라고 가정해보면, A와 B를 연결하는 해저터널을 만들 때 환경부담금을 구해보자.

  먼저, 해저터널 길이는 루트( (0 - 0)^2 + (100 - 0)^2 ) 이 될 것이고, 여기에 제곱한 값은 (0 - 0)^2 + (100 - 0)^2 이 될 것이다.

  이 값 곱하기 환경부담세율인 1을 곱한값이 환경부담금이 된다.

  이렇게, 만들 수 있는 모든 해저터널의 환경부담금을 구해서, 벡터에 저장해주자 !

 

  이후 과정은, 크루스칼 알고리즘을 그대로 적용하면 된다. 위의 크루스칼에 대한 글을 읽고 왔다면 어렵지 않게 구현할 수

  있을 것이다.


[ 소스코드 ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<cstring>
 
typedef long long ll;
 
#define endl "\n"
#define MAX 1000 + 1
using namespace std;
 
typedef struct
{
    ll x;
    ll y;
}Pos;
 
ll N;
ll Answer;
ll Parent[MAX];
 
double E;
Pos P[MAX];
vector<pair<ll, pair<ll, ll>>> Edge;
 
void Initialize()
{
    memset(Parent, 0sizeof(Parent));
    N = Answer = 0;
    E = 0.0;
    Edge.clear();
    for (int i = 0; i < MAX; i++)
    {
        P[i].x = -1;
        P[i].y = -1;
    }
}
 
ll Calc_Dist(int i, int j)
{
    ll dx = (P[i].x - P[j].x) * (P[i].x - P[j].x);
    ll dy = (P[i].y - P[j].y) * (P[i].y - P[j].y);
 
    return dx + dy;
}
 
void Input()
{
    cin >> N;
 
    for (int i = 1; i <= N; i++)
    {
        ll a; cin >> a;
        P[i].x = a;
    }
    for (int i = 1; i <= N; i++)
    {
        ll a; cin >> a;
        P[i].y = a;
    }
 
    for (int i = 1; i <= N; i++)
    {
        for (int j = i + 1; j <= N; j++)
        {
            ll Dist = Calc_Dist(i, j);
            Edge.push_back(make_pair(Dist, make_pair(i, j)));
        }
    }
    cin >> E;
}
 
int Find(int x)
{
    if (Parent[x] == x) return x;
    else return Parent[x] = Find(Parent[x]);
}
 
bool SameParent(int x, int y)
{
    x = Find(x);
    y = Find(y);
 
    if (x != y) return false;
    else return true;
}
 
void Union(int x, int y)
{
    x = Find(x);
    y = Find(y);
 
    if (x != y) Parent[y] = x;
}
 
void Solution()
{
    sort(Edge.begin(), Edge.end());
 
    for (int i = 1; i <= N; i++) Parent[i] = i;
 
    for (int i = 0; i < Edge.size(); i++)
    {
        if (SameParent(Edge[i].second.first, Edge[i].second.second) == false)
        {
            Union(Edge[i].second.first, Edge[i].second.second);
            Answer = Answer + Edge[i].first;
        }
    }
}
 
void Solve()
{
    int Tc; cin >> Tc;
    for (int T = 1; T <= Tc; T++)
    {
        Initialize();
        Input();
        Solution();
 
        cout << "#" << T << " " << (double)(Answer * E) << endl;
    }
}
 
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout << fixed;
    cout.precision(0);
 
    //freopen("Input.txt", "r", stdin);
    Solve();
 
    return 0;
}
cs

 

 

  


'[ SWEA Code ] > # SWEA - ' 카테고리의 다른 글

[ SWEA 1873 ] 상호의 배틀필드 (C++)  (0) 2019.03.10
[ SWEA 1213 ] String (C++)  (0) 2019.03.04
[ SWEA 1211 ] Ladder2 (C++)  (0) 2019.02.20
[ SWEA 1244 ] 최대상금 (C++)  (0) 2019.02.19
[ SWEA 1210 ] Ladder1 (C++)  (0) 2019.02.19

+ Recent posts