給定n個活動,其中的每個活動ai包含乙個起始時間si與結束時間fi。設計與實現演算法從n個活動中找出乙個最大的相互相容的活動子集s。
要求:分別設計動態規劃與貪心演算法求解該問題。其中,對貪心演算法分別給出遞迴與迭代兩個版本的實現。
對於上述問題,可簡化為上方,當上乙個活動結束後,才可以進行下乙個活動,對同一時間線來講,如上圖,從0-11,a與g滿足題意,由於a還未結束,b就開始,所以a與b不滿足題意。
要尋找最大互相相容子集s,顯然要確定每乙個活動的開始時間與結束時間。即需要確定活動的次序,我們以活動結束時間作為標準對活動進行排序。如下例:
顯然,可以得到兩個最大相容子集。
首先我們用動態規劃的思想來解決上述問題。
1、定義子問題:我們定義sij滿足存在ak使得fi<=sk<=fk<=sj,形象來講就是存在ak活動使得它在ai結束之後,aj開始之前。即
那麼整個問題該怎麼去描述呢,活動1到活動n若表示為 s1n顯然並不包含活動1與活動n,這裡我們就增加兩個虛活動分別在兩端,即s0=0,sn+1=∞。
2、建立dp方程:定義完子問題,建立dp方程就相對簡單,顯然sij=sik+ak+skj。
3、求解dp方程:首先要尋找到符合相容子集的k值,自然就對i到j之間所有的k值遍歷一遍就可以。
可見動態規劃演算法的時間複雜度為o(n^3)int
dp(vector<
int>s, vector<
int>e)}}
/* for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
*/return c[0]
[n -1]
;}
貪心演算法較為簡單,這裡就不過多贅述。
遞迴實現:
迭代實現:void
recursive
(vector<
int> s, vector<
int> e,
int i,
int j)
}
void
iterative
(vector<
int>s, vector<
int>e)
;int i =1;
for(
int m =
2; m < s.
size()
-1; m++)}
for(
int i =
0; i < a.
size()
; i++
) cout << a[i]
<<
" ";
}
區間排程問題 貪心演算法
問題 有 n 項工作,每項工作分別在 s i 時間開始,在 t i 時間結束 對於每項 工作,你都有可以選擇參與與否。如果選擇了參與,那麼自始自終都必須全程參與。此外,參與工作的時間段不能重疊 即使是開始的瞬間和結束的瞬間的重疊也 是不允許的 include include include usin...
區間排程問題 貪心演算法
一 題目 區間排程問題 有n項工作,每項工作分別在si時間開始,在ti時間結束。對於每項工作,你都可以選擇參與與否。如果選擇了參與,那麼自始至終都必須全程參與。此外,參與工作的時間段不能重複 即使是開始的瞬間和結束的瞬間的重疊也是不允許的 你的目標是參與盡可能多的工作,那麼最多能參與多少項工作呢?1...
區間排程 貪心演算法
一 找到數目盡可能多的相容任務 假設每個任務j從sj開始到fj結束。若要找到盡可能多的相容任務,只需要將所有任務按照結束時間排序,每次都選擇最早結束的那個任務。因為每次選最早結束的,則留給之後的時間就越多。在餘下的時間中與被選的那個任務衝突的任務最多也只能有乙個被選 代替現在被選的這個任務 但是留下...