[英]How to prefer longer intervals in weighted interval scheduling
加權間隔調度有一個相當容易實現的快速解決方案。 這是python中的一些代碼:
# A class to store a Job
class Job:
def __init__(self, start, finish, profit):
self.start = start
self.finish = finish
self.profit = profit
# Function to perform a binary search on the given jobs, which are sorted
# by finish time. The function returns the index of the last job, which
# doesn't conflict with the given job, i.e., whose finish time is
# less than or equal to the given job's start time.
def findLastNonConflictingJob(jobs, n):
# search space
(low, high) = (0, n)
# iterate till the search space is exhausted
while low <= high:
mid = (low + high) // 2
if jobs[mid].finish <= jobs[n].start:
if jobs[mid + 1].finish <= jobs[n].start:
low = mid + 1
else:
return mid
else:
high = mid - 1
# return the negative index if no non-conflicting job is found
return -1
# Function to print the non-overlapping jobs involved in maximum profit
# using dynamic programming
def findMaxProfitJobs(jobs):
# sort jobs in increasing order of their finish times
jobs.sort(key=lambda x: x.finish)
print([(jobs[i].start, jobs[i].finish) for i in range(len(jobs))])
# get the number of jobs
n = len(jobs)
# `maxProfit[i]` stores the maximum profit possible for the first `i` jobs, and
# `tasks[i]` stores the index of jobs involved in the maximum profit
maxProfit = [None] * n
tasks = [[] for _ in range(n)]
# initialize `maxProfit[0]` and `tasks[0]` with the first job
maxProfit[0] = jobs[0].profit
tasks[0].append(0)
# fill `tasks[]` and `maxProfit[]` in a bottom-up manner
for i in range(1, n):
# find the index of the last non-conflicting job with the current job
index = findLastNonConflictingJob(jobs, i)
# include the current job with its non-conflicting jobs
currentProfit = jobs[i].profit
if index != -1:
currentProfit += maxProfit[index]
# if including the current job leads to the maximum profit so far
if maxProfit[i - 1] <= currentProfit:
maxProfit[i] = currentProfit
if index != -1:
tasks[i] = tasks[index]
tasks[i].append(i)
# excluding the current job leads to the maximum profit so far
else:
tasks[i] = tasks[i - 1][:]
maxProfit[i] = maxProfit[i - 1]
# `maxProfit[n-1]` stores the maximum profit
print("The maximum profit is", maxProfit[n - 1])
# `tasks[n-1]` stores the index of jobs involved in the maximum profit
print("The jobs involved in the maximum profit are", end=' ')
for i in tasks[n - 1]:
print((jobs[i].start, jobs[i].finish, jobs[i].profit), end=' ')
if __name__ == '__main__':
jobs = [
Job(0, 3, 4), Job(0, 7, 8), Job(4, 7, 4)
]
findMaxProfitJobs(jobs)
代碼輸出:
The jobs involved in the maximum profit are (0, 3, 4) (4, 7, 4)
在這種情況下,兩個區間 (0,3) 和 (4,7) 的兩個權重之和與區間 (0, 7) 的權重相同。 發生這種情況時,我希望算法返回單個較長的間隔,但此代碼返回兩個較短的間隔。
如何修改代碼/算法以更喜歡更長的間隔作為決勝局?
正確的標准不是更長的間隔,而是更少的間隔數。 所以我們使用兩個標准來解決:
注意:當前代碼的一個問題是使用淺拷貝而不是深拷貝,即
tasks[i] = tasks[i - 1][:] # Shallow copy
tasks[i] = deepcopy(tasks[i-1] # Deep copy
在提供正確利潤的同時使用淺拷貝會在更復雜的情況下提供錯誤的工作。
代碼
from copy import deepcopy
# A class to store a Job
class Job:
def __init__(self, start, finish, profit):
self.start = start
self.finish = finish
self.profit = profit
# Function to perform a binary search on the given jobs, which are sorted
# by finish time. The function returns the index of the last job, which
# doesn't conflict with the given job, i.e., whose finish time is
# less than or equal to the given job's start time.
def findLastNonConflictingJob(jobs, n):
# search space
(low, high) = (0, n)
# iterate till the search space is exhausted
while low <= high:
mid = (low + high) // 2
if jobs[mid].finish <= jobs[n].start:
if jobs[mid + 1].finish <= jobs[n].start:
low = mid + 1
else:
return mid
else:
high = mid - 1
# return the negative index if no non-conflicting job is found
return -1
# Function to print the non-overlapping jobs involved in maximum profit
# using dynamic programming
def findMaxProfitJobs(jobs):
# sort jobs in increasing order of their finish times
jobs.sort(key=lambda x: x.finish)
print([(jobs[i].start, jobs[i].finish) for i in range(len(jobs))])
# get the number of jobs
n = len(jobs)
# `maxProfit[i]` is a tuple containing the maximum profit possible for the
# first `i` jobs and the negative of the number of jobs to achieve
# this profit. We use negative intervals since when looking for max,
# the number of intervals will be minimized as a tie-breaker on profit
# `tasks[i]` stores the index of jobs involved in the maximum profit
maxProfit = [None] * n
tasks = [[] for _ in range(n)]
# initialize `maxProfit[0]` and `tasks[0]` with the first job
maxProfit[0] = (jobs[0].profit, -1)
tasks[0].append(0)
# fill `tasks[]` and `maxProfit[]` in a bottom-up manner
for i in range(1, n):
# find the index of the last non-conflicting job with the current job
index = findLastNonConflictingJob(jobs, i)
# include the current job with its non-conflicting jobs
currentProfit = (jobs[i].profit, -1) # (profit, negative of number of jobs)
if index != -1:
# current tuple of profit and negative of number of intervals
currentProfit = (currentProfit[0] + maxProfit[index][0],
currentProfit[1] + maxProfit[index][1])
# if including the current job leads to the maximum profit so far
if maxProfit[i - 1] <= currentProfit:
# comparison of tuple based upon profit and number of jobs
maxProfit[i] = currentProfit
if index != -1:
tasks[i] = deepcopy(tasks[index])
tasks[i].append(i)
# excluding the current job leads to the maximum profit so far
else:
tasks[i] = deepcopy(tasks[i - 1])
maxProfit[i] = maxProfit[i - 1]
# `maxProfit[n-1]` stores the maximum profit
print("The maximum profit is", maxProfit[n - 1])
# `tasks[n-1]` stores the index of jobs involved in the maximum profit
print("The jobs involved in the maximum profit are", end=' ')
for i in tasks[n - 1]:
print((jobs[i].start, jobs[i].finish, jobs[i].profit), end=' ')
print()
if __name__ == '__main__':
# Test 1
print('Test 1')
jobs = [
Job(0, 3, 4), Job(0, 7, 8), Job(4, 7, 4)
]
findMaxProfitJobs(jobs)
# Test 2
print('\nTest 2')
jobs = [
Job(2, 2, 50), Job(3, 5, 20), Job(6, 19, 100), Job(2, 100, 200)
]
findMaxProfitJobs(jobs)
輸出
Test 1
[(0, 3), (0, 7), (4, 7)]
The maximum profit is (8, -1)
Tasks [[0], [1], [1]]
The jobs involved in the maximum profit are (0, 7, 8)
Test 2
[(2, 2), (3, 5), (6, 19), (2, 100)]
The maximum profit is (250, -2)
Tasks [[0], [0, 1], [0, 1, 2], [0, 3]]
The jobs involved in the maximum profit are (2, 2, 50) (2, 100, 200)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.