PS

[BOJ] 9946번 : 아이템 제작

yunny_world 2022. 12. 23. 18:31

Vermeil의 추천 문제.. 감사요!
이런 발상 쓰는 문제 처음 만나봐서 신기해서 글로 써둘까 한다.


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

9446번: 아이템 제작

첫째 줄에는 아이템 종류의 수 n과 제작 방법의 수 m이 주어진다. (1 ≤ n ≤ 10,000, 0 ≤ m ≤ 100,000) 둘째 줄에는 각 아이템의 가격 ci가 아이템 번호가 증가하는 순서대로 주어진다. (0 ≤ ci ≤ 109)

www.acmicpc.net


풀이

일단 이 문제의 핵심은

x + y → a 와 같이 제작할 수 있다면,
간선 x → a의 비용은 y까지의 최소 비용,
간선 y → a의 비용은 x까지의 최소 비용

이라는 점이다.
처음에는 0번 정점에서 시작해서 아이템을 구매하는 것을 의미하는 간선을 추가하려 했다.
하지만, 다익스트라 돌리는 과정에서 '구매'와 '제작'을 구분해서 구현해야 해서 위 방법은 불편하다는 것을 깨달았다.

따라서, 처음에 모든 '구매'를 미리 처리해주어 다익스트라 돌릴 때에는 '제작'만 처리하면 되도록 하여 구현했다.

원래 내가 풀었던 다익스트라 문제들는 이미 간선의 비용이 정해진 이후에 다익스트라를 돌렸었는데,
이 문제는 간선의 비용이 다익스트라를 돌리는 과정에서 정해지는 점이 신기했다..


코드

ll n, m;
vector<pll> g[10005];
ll c[10005];
priority_queue<pll> pq;

ll dijkstra()
{
    pq.push({ 0, 0 });
    c[0] = 0;
    while (!pq.empty())
    {
        ll cost = -pq.top().X;
        ll now = pq.top().Y;
        pq.pop();
        if (cost > c[now]) continue;
        for (auto x : g[now])
        {
            ll nxt = x.X;
            ll nxtCost = cost + c[x.Y];
            if (nxtCost < c[nxt])
            {
                pq.push({ -nxtCost, nxt });
                c[nxt] = nxtCost;
            }
        }
    }
    return c[1];
}

void solve()
{
    cin >> n >> m;
    fill(c, c + 10005, LLONG_MAX);
    for (int i = 1; i <= n; i++)
    {
        ll x; cin >> x;
        pq.push({ -x, i });
        c[i] = x;
    }
    for (int i = 0; i < m; i++)
    {
        ll a, x, y; cin >> a >> x >> y;
        g[x].push_back({ a, y });
        g[y].push_back({ a, x });
    }
    cout << dijkstra();
}


'PS' 카테고리의 다른 글

[BOJ] 9466번 : 텀 프로젝트  (0) 2023.01.12
x와 가장 가까운 수 y 찾기  (1) 2022.12.26
22/12/04 PS  (2) 2022.12.04
[BOJ] 18240번 : 이진 탐색 트리 복원하기  (0) 2022.11.18
[BOJ] 2812번 : 크게 만들기  (2) 2022.11.18