From 61d465bba93ddb41cc434f371e84d4ec9dde2254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A0=9C=ED=9D=AC?= <103947888+pinkkj@users.noreply.github.com> Date: Thu, 27 Nov 2025 23:37:46 +0900 Subject: [PATCH] =?UTF-8?q?251127=20:=20[BOJ=2017612]=20=EC=87=BC=ED=95=91?= =?UTF-8?q?=EB=AA=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _jehui/17512.ipynb | 183 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 _jehui/17512.ipynb diff --git a/_jehui/17512.ipynb b/_jehui/17512.ipynb new file mode 100644 index 00000000..7875c253 --- /dev/null +++ b/_jehui/17512.ipynb @@ -0,0 +1,183 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9d68b7b9", + "metadata": {}, + "source": [ + "# 첫번째 시도" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "65521161", + "metadata": {}, + "outputs": [], + "source": [ + "import heapq\n", + "q = []\n", + "N, K = map(int, input().split())\n", + "for table in range(1, K+1):\n", + " num, w = map(int, input().split())\n", + " heapq.heappush(q, [w, -table, num])\n", + "\n", + "next_person = K + 1\n", + "result = 0\n", + "mul_num = 1\n", + "while q:\n", + " # 가장 빨린 끝난 사람 종료\n", + " end_w, end_table, end_num = heapq.heappop(q)\n", + " # 정답 갱신\n", + " result += mul_num * end_num\n", + " mul_num += 1\n", + " # 남은 시간\n", + " for i in range(len(q)):\n", + " q[i][0] -= end_w\n", + " if next_person < N+1:\n", + " # 새로운 사람 등장\n", + " num, w = map(int, input().split())\n", + " heapq.heappush(q, [w, end_table, num]) \n", + " # 다음 사람\n", + " next_person += 1\n", + "print(result)" + ] + }, + { + "cell_type": "markdown", + "id": "82c0eea4", + "metadata": {}, + "source": [ + "[문제]\n", + "- 시간 초과\n", + "- 13900이 나와야 하는데, 13942가 나옴.
\n", + "\n", + "[시간복잡도]
\n", + "O(N*K)" + ] + }, + { + "cell_type": "markdown", + "id": "ba08a144", + "metadata": {}, + "source": [ + "# 피드백\n", + "## 1. 로직 / 정확도 관점에서 문제점\n", + "1. N < K일 때 입력 초과\n", + "```py\n", + "for table in range(1, K+1):\n", + " num, w = map(int, input().split())\n", + "```\n", + "N이 K보다 작으면, 존재하지 않는 줄을 읽으려고 해서 바로 런타임 에러 터짐.\n", + "→ range(1, min(N, K)+1) 로 해야 돼.\n", + "\n", + "2. “가장 적게 기다리는 계산대” 규칙이 제대로 구현 안 됨\n", + "\n", + "지금 로직은:\n", + "- 처음 K명은 계산대 1~K에 한 명씩.\n", + "- 이후엔 항상 방금 끝난 계산대에만 다음 사람을 붙임.\n", + "\n", + "하지만 문제는 “현재까지의 예상 대기시간이 가장 짧은 계산대”를 골라야 하니까,\n", + "실제로는 K개의 계산대 각각의 누적 작업량(언제 비는지) 를 관리하면서\n", + "항상 그중 최소인 계산대에 배정해야 해.\n", + "\n", + "지금 코드는 “끝나는 순서대로만 붙이는” 방식이라\n", + "원래 문제의 시뮬레이션이랑은 좀 다름. -> 동시에 끝나면 번호 작은곳에 넣어야 하는데, 지금은 그냥 번호 큰곳에 넣고 있음\n", + "\n", + "3. 시간을 계속 깎는 방식 자체가 비효율적\n", + "한 번 pop할 때마다 for i in range(len(q)): 로\n", + "모든 사람의 남은 시간을 줄이는 설계가 문제의 원인이야.\n", + "\n", + "사실 이건 안 해도 되고, “절대 시각(완료 시간)” 만 관리하면 돼.\n", + "\n", + "## 2. 어떻게 바꿔야 하는지 (권장 방식)\n", + "### 핵심 아이디어\n", + "\n", + "- 계산대 힙: (현재까지의 누적 시간, 계산대 번호)\n", + "→ 새 손님을 항상 이 힙의 top 계산대에 배정\n", + "\n", + "- 동시에, 각 손님의 퇴장 정보를 (퇴장시간, -계산대번호, 회원번호) 형태로 배열에 모아서\n", + "마지막에 정렬한 뒤, 1×r₁ + 2×r₂ + … 계산.\n", + "\n", + "이렇게 하면 매 손님당\n", + "- 힙 pop + push → O(log K)\n", + "\n", + "이므로 전체:\n", + "O(N log K) (+ 마지막 정렬 O(N log N))\n", + "정도로 깔끔하게 떨어져." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "194151e6", + "metadata": {}, + "outputs": [], + "source": [ + "import heapq\n", + "import sys\n", + "input = sys.stdin.readline\n", + "\n", + "N, K = map(int, input().split())\n", + "customers = [tuple(map(int, input().split())) for _ in range(N)] # (id, w)\n", + "\n", + "pq = [] # (finish_time, counter_idx, customer_id)\n", + "exit_list = [] # (finish_time, -counter_idx, id)\n", + "\n", + "cnt = min(N, K)\n", + "\n", + "# 처음 K명 계산대 배치\n", + "for i in range(cnt):\n", + " cid, w = customers[i]\n", + " heapq.heappush(pq, (w, i+1, cid)) # 계산대 1~K\n", + "\n", + "next_idx = cnt # 다음 고객 index\n", + "\n", + "# K명 이후 고객 처리\n", + "while next_idx < N:\n", + " finish_time, counter, cid = heapq.heappop(pq)\n", + " exit_list.append((finish_time, -counter, cid))\n", + "\n", + " new_id, new_w = customers[next_idx]\n", + " heapq.heappush(pq, (finish_time + new_w, counter, new_id))\n", + " next_idx += 1\n", + "\n", + "# 계산대에 남은 고객 처리\n", + "while pq:\n", + " finish_time, counter, cid = heapq.heappop(pq)\n", + " exit_list.append((finish_time, -counter, cid))\n", + "\n", + "# 퇴장 규칙 정렬\n", + "exit_list.sort()\n", + "\n", + "# 정답 계산\n", + "ans = 0\n", + "for i, (_, _, cid) in enumerate(exit_list, start=1):\n", + " ans += i * cid\n", + "\n", + "print(ans)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "ann_env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.20" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}