論貪心策略的選擇 對區間排程問題的再思考

2021-09-24 04:10:18 字數 1770 閱讀 4153

—— 對區間排程問題的再思考

演算法設計c4.1中引入了無權區間排程問題,這一問題的貪心策略為按照任務結束時間排序。

這一策略是如何得到的呢?教科書給出的方法是先想出若干可以進行排序的維度,然後通過舉反例的方式去進行驗證,最後刪去錯誤的,留下正確的貪心策略。然而,這樣的思考方式在面對實際問題的時候實際上很容易出錯。其一,可能壓根想不到正確的貪心策略(開始的策略集合中就沒有正確策略);其二,可能無法舉出反例否決錯誤的貪心策略。

那麼,我們是否有其他方式來思考貪心策略呢?在此,我將嘗試通過dp來反向得到貪心策略。啟發這一思路的靈感**於c6.1的有全區間排程問題。

在有權區間排程問題中,我們注意到,區域性最優解未必能構成全域性最優解,我們需要對每個最優子結構的結果進行組合,才能得到最後的全域性最優解。又很容易注意到,無權區間排程問題實際上就是有全區間排程問題在區間權值全部為1的乙個特例,或者說是乙個弱化情況。很自然的可以想到,我們是否可以通過觀察dp過程,反向得到正確的貪心策略呢?

這一問題的答案是肯定的。注意到,在有權區間排程問題中,我們很容易可以得到dp方程,而這一方程的前提是我們需要對任務進行預先排序。隨後,我們可以通過把遞迴轉換成迴圈,得到複雜度僅為o(n)的dp解(此處假設任務已經完成排序)。

那麼如何對任務進行排序,以顯示其先後關係呢?自然,我們需要使用任務的時間屬性,即開始時間和結束時間。緊跟著的問題就是,我們應該如何用時間屬性進行排序呢?單純用開始時間,或結束時間,亦或是二者共同使用做多維度排序?對這一問題的解答,可以通過在腦海中模擬實際的演算法流程得到,如下所述。

假設這樣乙個情景,已經通過某種順序對任務進行了排序,現在對於任務列表中乙個給定的任務,此處稱作p(i),我們應如何找到其前方與其不衝突的任務呢?如果按照開始時間排序,可以想到,我們需要遍歷此任務之前的所有任務,判定其結束時間,如果其結束早於開始則加入不衝突任務集合。如果按照結束時間排序,我們就可以倒序遍歷,直到遇到任務p(j),其結束時間早於開始時間,我們就可以直接把p(j)的不衝突集合s(j)複製過來,然後加上自己,即當前任務p(i)。換句話說,只要我們發現這樣的任務p(j),我們便可以知道,p(j)p(j)之前的任務,一定都與p(i)相容。如果使用結束時間排序,我們可以通過串聯前方的結果,來減小時間開銷,但是這一串聯操作在使用開始時間進行排序時是不可行的,因為開始時間並不能保證這一性質(找到p(j)後就能確定之前任務全部相容)。由此,我們知道了,對於區間排程問題,按照結束時間排序有利於降低後續步驟的時間複雜度。

然後,我們開始嘗試從dp解法反推回貪心解法。先考慮dp解法,在排序之後,我們先從最後乙個任務開始遞迴;改寫成迴圈形式,則是我們從開頭開始,對每個任務判斷,是在結果集中加入任務值得,還是不加入值得。由此,我們可以得到迴圈中的dp方程:dp[i]=max,其中t[i]為用於儲存最近的相容任務(也即上文所述的p(j))。再回到貪心,我們注意到,第乙個任務必然會被選擇,而當權值為1的時候,dp[i-1]總會小於等於dp[t[i]]+1,所以我們相當於會從第乙個任務開始,不斷選擇相容任務,最後得到結果集。由此,我們得到了我們的貪心策略。

綜上,本文描述了一種從dp出發得到貪心策略的思路,極大的降低了找不到正確貪心策略的風險。希望本文對您有所幫助。

Algorithm 貪心策略之區間排程問題

describe 有n項工作,每項工作分別再si時間開始,在ti時間結束 對於每項工作,你都可以參與與否,如果選擇參與,那麼自始自終都必須全程參與 此外參加工作的時間段不能重複 即使是開始的瞬間和結束的瞬間的重疊也不允許 你的目標是參與盡可能多的工作,那麼最多能參與多少項工作呢?1 n 100000...

區間排程問題(貪心)

問題描述 有n項工作,每項工作分別在si開始,ti結束。對每項工作,你都可以選擇參加或不參加,但選擇了參加某項工作就必須至始至終參加全程參與,即參與工作的時間段不能有重疊 即使開始的時間和結束的時間重疊都不行 問最多可以完成多少項工作?限制條件 1 n 100000 1 si ti 10 9 第二行...

貪心解決區間排程問題

有n項工作,每項工作分別在si開始,ti結束。對每項工作,你都可以選擇參加或不參加,但選擇了參加某項工作就必須至始至終參加全程參與,即參與工作的時間段不能有重疊 即使開始的時間和結束的時間重疊都不行 目標 參與盡可能多的工作,那麼最多能參與多少項工作 限制條件 1 n 100000 1 si ti,...