diff --git a/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_1.py b/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_1.py new file mode 100644 index 0000000..d28d2d5 --- /dev/null +++ b/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_1.py @@ -0,0 +1,31 @@ +# startTimeでソートして、繋げられるものを順番に確認していく +# 終了時刻の早いものから見ていき、最大の利益になるものを選択していく +# (最大の利益にならないものは、それ以降でも最大にならないため捨てて良い) +# 例:(start, end, profit) = ((1, 3 50), (2, 3, 10), (3, 5, 40), (4, 6, 70)) +# 3項目の選択肢は +# (1, 3, 50) -> (3, 5, 40)の順番で選択すると最大の利益になる +# (2, 3, 10) -> (3, 5, 40)は最大の利益にならない(4項目以降でも最大の利益にならないので捨てる) +# 4項目の選択肢は +# (1, 3, 50) -> (4, 6, 70)の順番で選択すると最大の利益になる +# (2, 3, 10)は3項目の検討時に捨てた +class Solution: + def jobScheduling( + self, startTime: List[int], endTime: List[int], profit: List[int] + ) -> int: + sorted_starts = sorted([(startTime[i], i) for i in range(len(startTime))]) + max_profit = 0 + end_profit_heap = [(0, 0)] + for start, i in sorted_starts: + max_profit_use_i = 0 + pre_info = () + while end_profit_heap and end_profit_heap[0][0] <= start: + pre_end, pre_profit = heapq.heappop(end_profit_heap) + if pre_profit + profit[i] <= max_profit_use_i: + continue + max_profit_use_i = pre_profit + profit[i] + pre_info = (pre_end, pre_profit) + heapq.heappush(end_profit_heap, (endTime[i], max_profit_use_i)) + max_profit = max(max_profit, max_profit_use_i) + if pre_info: + heapq.heappush(end_profit_heap, pre_info) + return max_profit diff --git a/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_2.py b/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_2.py new file mode 100644 index 0000000..efddd83 --- /dev/null +++ b/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_2.py @@ -0,0 +1,21 @@ +# DP +# i番目以降のjobを使った時の最大利益をメモしていく +class Solution: + def jobScheduling( + self, startTime: List[int], endTime: List[int], profit: List[int] + ) -> int: + jobs = list(zip(startTime, endTime, profit)) + jobs.sort() + max_profit_begin_i = [None] * len(jobs) + max_profit_begin_i.append(0) + + def find_max_profit(i): + if max_profit_begin_i[i] is not None: + return max_profit_begin_i[i] + profit_skip_i = find_max_profit(i + 1) + next_index = bisect.bisect_left(jobs, (jobs[i][1], 0, 0), lo=i + 1) + profit_use_i = find_max_profit(next_index) + jobs[i][2] + max_profit_begin_i[i] = max(profit_skip_i, profit_use_i) + return max_profit_begin_i[i] + + return find_max_profit(0) diff --git a/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_3.py b/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_3.py new file mode 100644 index 0000000..9922615 --- /dev/null +++ b/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_3.py @@ -0,0 +1,17 @@ +class Solution: + def jobScheduling( + self, startTime: List[int], endTime: List[int], profit: List[int] + ) -> int: + jobs = list(zip(startTime, endTime, profit)) + jobs.sort() + + @cache + def find_max_profit(i): + if i >= len(jobs): + return 0 + profit_skip_i = find_max_profit(i + 1) + next_index = bisect_left(jobs, (jobs[i][1], 0, 0), lo=i + 1) + profit_use_i = find_max_profit(next_index) + jobs[i][2] + return max(profit_skip_i, profit_use_i) + + return find_max_profit(0) diff --git a/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_4.py b/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_4.py new file mode 100644 index 0000000..f7afc1a --- /dev/null +++ b/grind75_hard/07_1235_Maximum Profit in Job Scheduling/level_4.py @@ -0,0 +1,30 @@ +# DP +class Solution: + def jobScheduling( + self, startTime: List[int], endTime: List[int], profit: List[int] + ) -> int: + jobs = list(sorted(zip(startTime, endTime, profit))) + max_profit = [0] * (len(jobs) + 1) + for i in range(len(jobs) - 1, -1, -1): + profit_skip_running_job = max_profit[i + 1] + next_index = bisect_left(jobs, (jobs[i][1], 0, 0), lo=i + 1) + profit_use_running_job = max_profit[next_index] + jobs[i][2] + max_profit[i] = max(profit_skip_running_job, profit_use_running_job) + return max_profit[0] + + +# level_1の書き直し +class Solution: + def jobScheduling( + self, startTime: List[int], endTime: List[int], profit: List[int] + ) -> int: + jobs = list(sorted(zip(startTime, endTime, profit))) + jobs.append((float("inf"), float("inf"), 0)) + max_profit = 0 + running_jobs = [] + for job_start, job_end, job_profit in jobs: + while running_jobs and running_jobs[0][0] <= job_start: + _, max_profit_from_running_job = heapq.heappop(running_jobs) + max_profit = max(max_profit, max_profit_from_running_job) + heapq.heappush(running_jobs, (job_end, max_profit + job_profit)) + return max_profit