Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

15-mjj111 #226

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

15-mjj111 #226

wants to merge 2 commits into from

Conversation

mjj111
Copy link
Collaborator

@mjj111 mjj111 commented Sep 14, 2024

πŸ”— 문제 링크

https://www.codetree.ai/training-field/frequent-problems/problems/codetree-tour/description?page=1&pageSize=5
μ½”λ“œνŠΈλ¦¬ νˆ¬μ–΄

βœ”οΈ μ†Œμš”λœ μ‹œκ°„

1μ‹œκ°„ 20λΆ„

✨ μˆ˜λ„ μ½”λ“œ

5가지 λͺ…령에 λŒ€ν•΄ μ•„λž˜μ™€ 같이 λ™μž‘ν•©λ‹ˆλ‹€.

  1. 닀리 건섀 -> λ‹€ μ—°κ²°ν•˜λ©΄ 0λΆ€ν„° λ‹€μ΅μŠ€νŠΈλΌλ‘œ κ°’ 계산
    1λ„μ‹œμ™€ 2λ„μ‹œλŠ” 3κ°€μ€‘μΉ˜ κ°„μ„ μœΌλ‘œ 이루어 μ§‘λ‹ˆλ‹€.

  2. μ—¬ν–‰ μƒν’ˆ 생성(3만번) -> ν˜„μž¬ 주어진 λ‹€μ΅μŠ€νŠΈλΌ 결과둜 μƒν’ˆμ„ λ§Œλ“­λ‹ˆλ‹€.
    1κ³ μœ μ‹λ³„μžλ‘œ 2맀좜 3도착지

  3. μ—¬ν–‰ μƒν’ˆ μ·¨μ†Œ(3만번) -> μ·¨μ†Œν•œ μƒν’ˆμ„ κΈ°λ‘ν•©λ‹ˆλ‹€.
    1κ³ μœ μ‹λ³„μžμ— ν•΄λ‹Ήν•˜λŠ” μ—¬ν–‰μƒν’ˆμ„ λͺ©λ‘μ—μ„œ μ‚­μ œ

  4. 졜적의 μ—¬ν–‰ μƒν’ˆ 판맀(3만번) 관리 λͺ©λ‘μ€ heapκ³Ό dict둜 κ΄€λ¦¬ν•œλ‹€. -> λ§Œμ•½ 뽑은 μƒν’ˆμ΄ νŒλ§€ν•˜μ§€ μ•ŠμŒμ΄λΌλ©΄ λ²„λ¦½λ‹ˆλ‹€.
    이득 - λΉ„μš©μ΄ μ΅œλŒ€μΉ˜μΈ μƒν’ˆμš°μ„  κ³ λ €(+id μ˜€λ¦„μ°¨μˆœ)
    λΉ„μš©μ€ μΆœλ°œμ§€λ‘œλΆ€ν„° id μƒν’ˆμ˜ 도착지 κΉŒμ§€ μ΅œλ‹¨κ±°λ¦¬
    λ§Œμ•½ λͺ©μ μ§€μ— λ„λ‹¬ν•˜λŠ”κ²Œ λΆˆκ°€λŠ₯ν•˜κ±°λ‚˜ λΉ„μš©μ΄ 이득보닀 크닀면 νŒλ§€λΆˆκ°€
    판맀 κ°€λŠ₯ν•œ μƒν’ˆμ€‘ κ°€μž₯ μš°μ„ μˆœμœ„κ°€ 높은 1개λ₯Ό νŒλ§€ν•˜μ—¬ ν•΄λ‹Ή idμƒν’ˆ μ‚­μ œ
    λ§Œμ•½ μ—†λ‹€λ©΄ -1 좜λ ₯ν•˜κ³  제거 x

  5. μƒν’ˆ μΆœλ°œμ§€ λ³€κ²½(15번) μΆœλ°œμ§€λΆ€ν„° λ‹€μ‹œ λ‹€μ΅μŠ€νŠΈλΌλ‘œ κ°’ 계산 ν›„ μƒν’ˆ λ‹€μ‹œ κ°±μ‹ / λ§Œμ•½ ν΄λž˜μŠ€κ°€ νŒλ§€ν•˜μ§€ μ•ŠμŒμ΄λΌλ©΄ μŠ€ν‚΅
    λͺ¨λ“  μΆœλ°œμ§€λ₯Ό s둜 λ³€κ²½ (변경함에 따라 각 μƒν’ˆμ˜ λΉ„μš©μ΄ λ³€κ²½λœλ‹€)

μ—¬ν–‰ λ§€λ‹ˆμ € 클래슀λ₯Ό λ¨Όμ € μ„ μ–Έν•΄μ€λ‹ˆλ‹€.

class TravelManager:
    def __init__(self, n):
        self.n = n  # λ„μ‹œμ˜ 수
        self.graph = defaultdict(list)  # λ„μ‹œ κ°„ κ°„μ„  정보
        self.distances = [INF] * n  # 0번 λ„μ‹œλΆ€ν„°μ˜ μ΅œλ‹¨ 거리
        self.products = {}  # μ—¬ν–‰ μƒν’ˆ 정보 (κ³ μœ μ‹λ³„μž -> (맀좜, 도착지))
        self.unavailable = set()  # νŒλ§€λ˜μ§€ μ•ŠλŠ” μƒν’ˆμ˜ κ³ μœ μ‹λ³„μž
        self.heap = []  # 졜적의 μƒν’ˆ 판맀λ₯Ό μœ„ν•œ νž™

100 (닀리건섀)λͺ…λ Ήμ–΄κ°€ λ¨Όμ € 주어지기 λ•Œλ¬Έμ— 이에 λŒ€ν•΄μ„œ Travel λ§€λ‹ˆμ €λ₯Ό μ„€μ •ν•΄μ£Όκ³ 
λ°›λŠ” κ°’λ§ˆλ‹€ μ—°κ²°ν•œ λ’€ λ§ˆμ§€λ§‰μ— λ‹€μ΅μŠ€νŠΈλΌλ₯Ό 톡해 0λΆ€ν„° κ°€μž₯ 짧은 길을 κ°±μ‹ ν•©λ‹ˆλ‹€.

def main():
    q = int(input())
    input_line = list(map(int, input().split()))

    n, m = input_line[1], input_line[2]
    manager = TravelManager(n)
    creations = input_line[3:]

    for i in range(0,len(creations),3):
        creation = creations[i:i+3]
        a = creation[0]
        b = creation[1]
        cost = creation[2]
        manager.add_road(a, b, cost)  
    manager.dijkstra(0)

μƒν’ˆμ΄ μΆ”κ°€λœλ‹€λ©΄ μ΄μ—λŒ€ν•΄μ„œ 이미 값을 ꡬ해놨기 λ•Œλ¬Έμ— μƒν’ˆμ— κ°±μ‹ ν•΄μ€λ‹ˆλ‹€.

    def add_product(self, product_id, revenue, destination):
        self.products[product_id] = (revenue, destination)
        cost = self.distances[destination]
        heapq.heappush(self.heap, (-(revenue - cost), product_id))  # μ΅œλŒ€ νž™ κ΅¬ν˜„

μƒν’ˆμ„ μ·¨μ†Œν•  경우 μ·¨μ†Œν•œ λͺ©λ‘μ— λ„£μ–΄μ€λ‹ˆλ‹€.

    def cancel_product(self, product_id):
        if product_id in self.products:
            self.unavailable.add(product_id)

κ°€μž₯ 졜고 μƒν’ˆμ„ νŒλ§€ν•˜κΈ° μœ„ν•΄μ„œ heap을 톡해 좜λ ₯ν•΄μ€λ‹ˆλ‹€.
μ—¬κΈ°μ„œ λ§Œμ•½ 이미 버린 μƒν’ˆμ΄λΌλ©΄ continueλ₯Ό 톡해 μ§€λ‚˜μΉ˜κ²Œλ©λ‹ˆλ‹€.

    def sell_best_product(self):
        while self.heap:
            profit, product_id = heapq.heappop(self.heap)

            if product_id in self.unavailable:
                continue  # νŒλ§€ν•˜μ§€ μ•ŠλŠ” μƒν’ˆμ€ λ¬΄μ‹œ

            revenue, destination = self.products[product_id]
            cost = self.distances[destination]
            if cost == INF or cost > revenue:
                print(-1)
                return

            print(product_id)
            del self.products[product_id]
            return
        print(-1)

도착지가 λ³€κ²½λœλ‹€λ©΄, λ‹€μ‹œ λ‹€μ΅μŠ€νŠΈλΌλ₯Ό 톡해 값을 κ°±μ‹ ν•΄μ£Όκ³ 
Heapa에 μžˆλŠ” λ‚΄μš©λ„ λ³€κ²½ν•΄μ€λ‹ˆλ‹€.

    def change_departure(self, new_start):
        self.dijkstra(new_start)
        self.heap = []
        for product_id, (revenue, destination) in self.products.items():
            if product_id not in self.unavailable:
                cost = self.distances[destination]
                heapq.heappush(self.heap, (-(revenue - cost), product_id))

πŸ“š μƒˆλ‘­κ²Œ μ•Œκ²Œλœ λ‚΄μš©

λΉ‘κ΅¬ν˜„μ€ ν™”κ°€ λ‚˜μ§€λ§Œ λ‹€ ν’€λ©΄ 쾌감이 μžˆλ„€μš”..γ…Ž
μž¬λ°ŒλŠ” λ¬Έμ œμ˜€μŠ΅λ‹ˆλ‹€.

Copy link
Collaborator

@9kyo-hwang 9kyo-hwang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

처음 λ‚Έ μ½”λ“œκ°€ μ‹œκ°„μ΄ˆκ³Ό λ‚˜κΈΈλž˜ 쓰읍 ν–ˆλŠ”λ°, λ‹€μ‹œ λ³΄λ‹ˆ 핡심은 "졜적 μƒν’ˆ"을 빨리 μ°ΎλŠ” κ²ƒμ΄μ—ˆκ΅°μš”...
λ‹€μ΅μŠ€νŠΈλΌλŠ” ν•΄λ΄€μž 16λ²ˆλ°–μ— λ°œμƒν•˜μ§€ μ•Šμ•„ μš°μ„ μˆœμœ„ν μ•ˆ μ“΄ $O(N^2)$으둜 해결이 λ˜λ„€μš” ν—ˆν—ˆ...

#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std;

int main() 
{
    cin.tie(nullptr)->sync_with_stdio(false);
    constexpr int INF = 1e9;

    int Q, Cmd; cin >> Q;

    int N, M;
    vector<vector<pair<int, int>>> Graph;
    vector<int> Distances;

    priority_queue<pair<int, int>> PriorityofProducts;
    unordered_map<int, pair<int, int>> Products;

    auto Dijkstra = [&](int Start)
    {
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> PQ;
        Distances.assign(N, INF);
        
        PQ.emplace(0, Start);
        Distances[Start] = 0;

        while(!PQ.empty())
        {
            const auto [du, u] = PQ.top(); PQ.pop();
            if(Distances[u] < du) continue;

            for(const auto& [v, dv] : Graph[u])
            {
                int Distance = du + dv;
                if(Distance < Distances[v])
                {
                    Distances[v] = Distance;
                    PQ.emplace(Distance, v);
                }
            }
        }
    };

    auto Construction = [&]()
    {
        cin >> N >> M;
        Graph.resize(N);

        while(M--)
        {
            int V, U, W; cin >> V >> U >> W;
            Graph[V].emplace_back(U, W);
            Graph[U].emplace_back(V, W);
        }

        Dijkstra(0);
    };

    auto Creation = [&]()
    {
        int Id, Revenue, Dest; cin >> Id >> Revenue >> Dest;
        Products[Id] = {Revenue, Dest};

        int Cost = Distances[Dest];
        int Benefit = Revenue - Cost;
        PriorityofProducts.emplace(Benefit, -Id);
    };

    auto Cancel = [&]()
    {
        int Id; cin >> Id;
        if(Products.count(Id) > 0)
        {
            Products.erase(Id);
        }
    };

    auto Sale = [&]()
    {
        int BestProductId = -1;
        while(!PriorityofProducts.empty())
        {
            auto [Benefit, Id] = PriorityofProducts.top(); PriorityofProducts.pop();
            Id *= -1;
            
            if(Products.count(Id) == 0) continue;
            
            const auto& [Revenue, Dest] = Products[Id];
            int Cost = Distances[Dest];

            if(Cost == INF || Cost > Revenue)
            {
                BestProductId = -1;
                break;
            }

            Products.erase(Id);
            BestProductId = Id;
            break;
        }

        return BestProductId;
    };

    auto Change = [&]()
    {
        int S; cin >> S;
        Dijkstra(S);
        
        PriorityofProducts = priority_queue<pair<int, int>>();
        for(const auto& [Id, Product] : Products)
        {
            const auto& [Revenue, Dest] = Product;
            int Cost = Distances[Dest];

            PriorityofProducts.emplace(Revenue - Cost, -Id);
        }
    };

    while(Q--)
    {
        cin >> Cmd;
        switch(Cmd)
        {
            case 100: Construction(); break;
            case 200: Creation(); break;
            case 300: Cancel(); break;
            case 400: cout << Sale() << "\n"; break;
            case 500: Change();
            default: break;
        }
    }

    return 0;
}

Copy link
Member

@gjsk132 gjsk132 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

μ§€κΈˆκΉŒμ§€λŠ” κ΅¬ν˜„μ΄ μž¬λ°ŒλŠ” 것 같은데, μœ„λ₯Ό 지킀고 μžˆλŠ” λ£¨λŒν”„κ°€ λ‘λ €μ›Œμš” πŸ₯²

전체 μ½”λ“œ

from heapq import *

input = open("input.txt").readline

cmd_cnt = int(input())

command = list(map(int,input().split()))[1:]

n, m = command[0], command[1]
limit = float("inf")

load_info = [[limit]*n for _ in range(n)]
dist = [limit]*n
p_id = {}
p_cost = []

for i in range(m):
    n1, n2, w = command[i*3+2:i*3+5]

    load_info[n1][n2] = min(w, load_info[n1][n2])
    load_info[n2][n1] = min(w, load_info[n2][n1])

def update_node_dist(s_node):
    
    hq = [(0, s_node)]
    check = [False]*n

    while hq and not all(check):
        w, current = heappop(hq)
        if check[current]:
            continue
        check[current] = True
        
        if w >= dist[current]:
            continue

        dist[current] = w

        for next in range(n):
            if next == current or load_info[current][next] == limit:
                continue
            heappush(hq, (w + load_info[current][next], next))

def update_product():
    update_cost = []

    for k, v in p_id.items():
        heappush(update_cost, ((dist[v[1]]-v[0]), k))
    
    return update_cost

update_node_dist(0)

for _ in range(cmd_cnt-1):
    command = list(map(int, input().split()))
    
    order = command[0]

    if order == 200:
        # 1 : id / 2 : revenue / 3 : dest
        cost = command[2] - dist[command[3]]
        heappush(p_cost, (-(command[2] - dist[command[3]]), command[1]))
        p_id[command[1]] = command[2:]

    elif order == 300:
        if command[1] in p_id:
            del(p_id[command[1]])
    
    elif order == 400:

        while True:
            if not p_cost:
                print(-1)
                break

            cost, id = heappop(p_cost)
            cost = -cost

            if not id in p_id.keys():
                continue
            
            elif cost < 0:
                heappush(p_cost, (-cost, id))
                print(-1)

            else:
                print(id)
                del(p_id[id])
            
            break
        
    else:
        dist = [limit]*n
        update_node_dist(command[1])
        p_cost = update_product()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants