ABC362 문제 해설

A 문제

문제는 매우 간단합니다. 세 정수 r, g, b와 문자열 c가 주어집니다. c가 "Red"이면 g와 b 중 최솟값을, "Blue"이면 r와 g 중 최솟값을, 그 외의 경우 r와 b 중 최솟값을 출력하면 됩니다.

코드 보기

#include<bits/stdc++.h>
using namespace std;

int main(){
    int red, green, blue;
    string color;
    cin >> red >> green >> blue >> color;
    
    if(color == "Red"){
        cout << min(green, blue);
    } else if(color == "Blue"){
        cout << min(red, green);
    } else {
        cout << min(red, blue);
    }
    return 0;
}

B 문제

세 점의 좌표가 주어졌을 때, 이들이 직각삼각형을 이루는지 판별하는 문제입니다. 먼저 세 점 사이의 거리를 각각 구하고, 가장 긴 변을 빗변으로 가정합니다. 피타고라스 정리에 따라 나머지 두 변의 제곱합이 빗변의 제곱과 일치하면 직각삼각형입니다. double형 연산에서는 오차가 발생할 수 있으므로, 차이가 1e-6 미만이면 같다고 판단합니다.

코드 보기

#include<bits/stdc++.h>
using namespace std;

struct Point {
    int x, y;
};

double calculateDistance(Point p1, Point p2){
    long long dx = p1.x - p2.x;
    long long dy = p1.y - p2.y;
    return sqrt((double)dx*dx + (double)dy*dy);
}

int main(){
    Point p[3];
    for(int i = 0; i < 3; ++i){
        cin >> p[i].x >> p[i].y;
    }
    
    double sides[3];
    sides[0] = calculateDistance(p[0], p[1]);
    sides[1] = calculateDistance(p[0], p[2]);
    sides[2] = calculateDistance(p[1], p[2]);
    
    sort(sides, sides + 3);
    
    double hypotenuse = sides[2];
    double leg1 = sides[0];
    double leg2 = sides[1];
    
    double left = leg1*leg1 + leg2*leg2;
    double right = hypotenuse*hypotenuse;
    
    if(fabs(left - right) < 1e-6){
        cout << "Yes";
    } else {
        cout << "No";
    }
    return 0;
}

C 문제

n개의 구간 [l_i, r_i]가 주어집니다. 각 구간에서 하나의 정수 a_i를 선택하여, 전체 합이 0이 되도록 하는 문제를 해결합니다. 먼저 모든 l_i의 합을 L, 모든 r_i의 합을 R라 하면, 합이 0이 가능하려면 L ≤ 0 ≤ R를 만족해야 합니다. 가능하다면, 초기값을 모두 l_i로 설정하고 합이 0이 될 때까지 차근차근 값을 늘려갑니다.

코드 보기

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n;
    cin >> n;
    
    vector<long long> left(n+1), right(n+1), answer(n+1);
    long long sumLeft = 0, sumRight = 0;
    
    for(int i = 1; i <= n; ++i){
        cin >> left[i] >> right[i];
        sumLeft += left[i];
        sumRight += right[i];
        answer[i] = left[i];
    }
    
    if(!(sumLeft <= 0 && sumRight >= 0)){
        cout << "No";
        return 0;
    }
    
    cout << "Yes" << '\n';
    long long needed = -sumLeft;
    
    for(int i = 1; i <= n && needed > 0; ++i){
        long long canIncrease = right[i] - left[i];
        if(needed >= canIncrease){
            answer[i] = right[i];
            needed -= canIncrease;
        } else {
            answer[i] += needed;
            needed = 0;
        }
    }
    
    for(int i = 1; i <= n; ++i){
        cout << answer[i] << " ";
    }
    return 0;
}

D 문제

이 문제는 가중치가 있는 그래프에서 최단 경로를 찾는 문제입니다. 각 정점에는 a_i라는 점수가 있고, 간선을 통과할 때 도착 정도의 점수를 간선 가중치에 포함시키면 됩니다. 즉, u에서 v로 가는 실제 비용은 w + a[v]가 됩니다. 다익스트라 알고리즘을 사용하여 1번 정점에서 다른 모든 정점까지의 최소 비용을 구하면 됩니다.

코드 보기

#include<bits/stdc++.h>
using namespace std;

struct Edge {
    int to;
    long long weight;
};

int main(){
    int vertex, edges;
    cin >> vertex >> edges;
    
    vector<long long> nodeValue(vertex + 1);
    for(int i = 1; i <= vertex; ++i){
        cin >> nodeValue[i];
    }
    
    vector<vector<Edge>> graph(vertex + 1);
    for(int i = 0; i < edges; ++i){
        int u, v, w;
        cin >> u >> v >> w;
        graph[u].push_back({v, w + nodeValue[v]});
        graph[v].push_back({u, w + nodeValue[u]});
    }
    
    const long long INF = 1e18;
    vector<long long> dist(vertex + 1, INF);
    vector<bool> visited(vertex + 1, false);
    dist[1] = nodeValue[1];
    
    priority_queue<pair<long long,int>, 
                   vector<pair<long long,int>>, 
                   greater<pair<long long,int>>> pq;
    pq.push({dist[1], 1});
    
    while(!pq.empty()){
        auto [d, cur] = pq.top();
        pq.pop();
        
        if(visited[cur]) continue;
        visited[cur] = true;
        
        for(const auto& e : graph[cur]){
            int next = e.to;
            long long cost = e.weight;
            if(dist[next] > dist[cur] + cost){
                dist[next] = dist[cur] + cost;
                pq.push({dist[next], next});
            }
        }
    }
    
    for(int i = 2; i <= vertex; ++i){
        cout << dist[i] << " ";
    }
    return 0;
}

태그: AtCoder algorithm Dijkstra Greedy geometry

6월 19일 01:43에 게시됨