貪心演算法 區間排程問題總結

2021-07-16 12:44:11 字數 4341 閱讀 5039

問題定義:存在單一資源,有一組以時間區間形式表示的資源請求reqs=,第i個請求希望占用資源一段時間來完成某些任務,這段時間開始於begin(i)終止於end(i)。如果兩個請求req-i和req-j在時間區間上沒有重疊,則說這兩個請求是相容的,求出這組請求的最大相容子集(最優子集)。舉個例子:有一間多**課室,某乙個週末有多個社團想要申請這間課室去舉辦社團活動,每個社團都有乙個對應的申請時間段,比如週六上午8:00-10:00。求出這間課室在這個週末最多能滿足幾個社團的需求。

解決方案:貪心演算法,優先選擇最早結束的需求,確保資源盡可能早地被釋放,把留下來滿足其他需求的時間最大化。具體偽**如下所示,演算法結束後集合a中會保留所有相容請求,a的大小即是最大相容數量。

初始化r是所有需求的集合,a為空集

對r中的需求ri,根據結束時間從早到晚排序

for ri in r, do

if ri與a中的請求相容

a = a並ri

endif

endfor

return

a

上述偽**的c++實現如下,

#include 

#include

#include

using

namespace

std;

const

int max_size = 100;

struct request req[max_size];

bool

operator

<(const request& req1, const request& req2)

int main()

for (int i = 0; i < requestnum; ++i)

sort(req, req + requestnum);

vector

rvec;

rvec.push_back(req[0]);

for (int i = 1; i < requestnum; ++i)

} cout

<< "最大兼容量: "

<< rvec.size() << endl;

return

0;}

問題定義:存在多個(或者無限多個)相同的資源,有一組以時間區間形式表示的資源請求reqs=,第i個請求希望占用資源一段時間來完成某些任務,這段時間開始於begin(i)終止於end(i)。如果兩個請求req-i和req-j在時間區間上沒有重疊,則說這兩個請求是相容的,用盡可能少的資源滿足所有請求(求最優資源數量)。舉個例子:有很多間課室,某個週末有多個社團需要申請課室辦活動,每個社團都有乙個對應的申請時間,求最少需要多少間課室才能夠滿足所有社團的需求(在這個問題之中時間重疊的社團需要安排在其他課室,即會使用到多個資源,需要考慮多個資源上的排程安排,故稱為多區間排程)。

解決方案:貪心演算法,將需求按照開始時間的早晚進行排序,然後開始為這些資源打標籤,每個標籤代表都乙個資源,需求req-i被打上標籤k表示該請求分配到的資源是k。遍歷排序後的需求,如果乙個需求與某個已分配資源上的其他安排不衝突,則把該需求也放進該資源的安排考慮中;如果衝突,那麼應該要給此需求分配新的資源,已用資源數量加一。具體操作的偽**如下所示。

對n個需求按照開始時間從早到晚進行排序

假設排序後的需求記為

初始化tagsize = 1;

for i=1 to n, do:

tags = ;

for j = 1 to i-1, do:

if rj與ri時間區間重疊產生衝突:

tags = tags - ;

endif

endfor

if tags為空集:

tagsize += 1;

將標籤tagsize貼在ri上

endif

else:

在tags剩下的標籤中隨便挑乙個貼給ri

endelse

endfor

此時每個請求上都貼有標籤,每個標籤對應其申請的資源編號,此時的tagsize就是至少需要的資源數量

return tagsize;

上述偽**的c++實現如下:

#include 

#include

#include

using

namespace

std;

const

int max_size = 100;

struct request req[max_size];

bool

operator

<(const request& req1, const request& req2)

int main()

for (int i = 0; i < requestnum; ++i)

sort(req, req + requestnum);

int tagsize = 1;

req[0].tag = 0;

bool tags[max_size];

for (int i = 1; i < requestnum; ++i)

}bool istagsempty = true;

int tag;

for (int j = 0; j < tagsize; ++j)

}if (istagsempty) else

} cout

<< "最小資源使用量: "

<< tagsize << endl;

return

0;}

問題定義:存在單一資源和一組資源請求reqs=,與前面兩個問題不同,這裡的資源從時刻0開始有效(開始接受申請,開始可以被使用),每個請求req-i都有乙個截止時間ddl(i),每個請求都要占用資源一段連續的時間來完成任務,占用時間為time(i)。每個請求都希望自己能在ddl之前完成任務,不同需求必須被分在不重疊的時間區間(單一資源,同一時刻只能滿足乙個請求)。假設我們計畫滿足每個請求,但是允許某些請求延遲(即某個請求在ddl之後完成,延誤工期),確定一種合理的安排,使得所有請求的延期時間中的最大值,是所有可能的時間安排情況中最小的。從時刻0開始,為每個請求req-i分配乙個長度time(i)的時間區間,把區間標記為[begin(i), end(i)],其中end(i) = begin(i) + time(i)。如果end(i) > ddl(i),則請求req-i被延遲,延遲時間為delay(i) = end(i) - ddl(i);否則delay(i) = 0。合理安排需求,使得maxdelay = max是所有可能的安排中最小的。

解決方案:貪心演算法,按照截止時間ddl排序,越早截止的任務越早完成。該演算法是乙個沒有空閒的最優排程,即從時刻0開始都有在處理請求,直到最後乙個請求執行完釋放資源之後才空閒。偽**如下所示。

將需求按照截止時間進行排序

假設排序後的截止時間為ddl[1]<=...<=ddl[n]

start = 0;

maxdelay = 0;

for i = 1

to n, do:

begin[i] = start;

end[i] = start + time[i];

start = end[i] + time[i];

if maxdelay < end[i] - ddl[i]:

l = end[i] - ddl[i];

endif

endfor

則每個任務安排的時間區間為[begin[i], end[i]],所有任務中最大的延遲為maxdelay,maxdelay為所有可能的任務安排中最小的延遲

return maxdelay;

上述**的c++實現如下:

#include 

#include

using

namespace

std;

const

int max_size = 100;

struct request req[max_size];

bool

operator

<(const request& req1, const request& req2)

int main()

for (int i = 0; i < requestnum; ++i)

sort(req, req + requestnum);

int start = 0, maxdelay = 0;

for (int i = 0; i < requestnum; ++i)

} cout

<< "最小的最大延遲: "

<< maxdelay << endl;

return

0;}

區間排程問題 貪心演算法

問題 有 n 項工作,每項工作分別在 s i 時間開始,在 t i 時間結束 對於每項 工作,你都有可以選擇參與與否。如果選擇了參與,那麼自始自終都必須全程參與。此外,參與工作的時間段不能重疊 即使是開始的瞬間和結束的瞬間的重疊也 是不允許的 include include include usin...

區間排程問題 貪心演算法

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

區間排程 貪心演算法

一 找到數目盡可能多的相容任務 假設每個任務j從sj開始到fj結束。若要找到盡可能多的相容任務,只需要將所有任務按照結束時間排序,每次都選擇最早結束的那個任務。因為每次選最早結束的,則留給之後的時間就越多。在餘下的時間中與被選的那個任務衝突的任務最多也只能有乙個被選 代替現在被選的這個任務 但是留下...