任務調度問題1—貪心算法


這個問題是《算法導論》上的一個經典的貪心算法問題——單處理器上具有期限和懲罰的單位時間任務調度問題,目標是使懲罰最小。

  輸入:第一行一個數n,接下來第2行到第n+1行,第i行分別是d[i]和w[i],其中d[i]表示第i個任務的時限,w[i]表示第i個任務的懲罰,每個任務的完成時間為單位時間。

  輸出:一行一個數,為最小懲罰。

  題解:

  令集合S為所有任務的集合,A為一個任務集合,其中所有的任務滿足條件:存在某種調配方式,使得所有任務能在期限前完成,又令l為所有A集合的集合。可以證明,序對M=(S,l)是一個擬陣,於是,可以采用貪心算法解決它。同時,一個任務集合R屬於l,當且僅當它滿足下列條件:

 R中在期限在不大於t的任務不大於t個。

  於是算法就出來了:先以w[i]為關鍵字進行排序,再進行枚舉:保持一個數組record[i]保存當前集合中時限在不大於i的任務個數,對於每一個任務ai,將d[i]之后的record更新(加1),若有一個d[j]不滿足條件,則繼續檢查下一個,反之,將它的懲罰從總懲罰中減去。最后得到的總懲罰即最小懲罰。

代碼:

 1 #include <iostream>
 2 #include <fstream>
 3 using namespace std;
 4 ifstream fin("TSP.in");
 5 ofstream fout("TSP.out");
 6 int w[2001],d[2001]; //w[i]指第i號任務的逾期懲罰,d[i]指第i號任務的期限,每個任務都是單位時間;
 7 int record[2001];
 8 int Max,ans;
 9 int partion(int *a,int start,int end)
10 {
11     int i=start,j=start-1,t=0;
12     for(i=start;i<=end;i++)
13     {
14       if(a[i]>=a[end])
15       {
16         j++;
17         t=a[i];
18         a[i]=a[j];
19         a[j]=t;
20         t=d[i]; 
21         d[i]=d[j];
22         d[j]=t;
23       }
24     }
25     return j;
26 }
27 int quicksort(int *a,int start,int end)
28 {
29 if(start>=end)
30 return 0;
31 int j=partion(a,start,end);
32 quicksort(a,start,j-1);
33 quicksort(a,j+1,end);
34 return 0;
35 }
36 int main()
37 {
38 int n=0,i=0,j=0;
39 fin>>n;
40 for(i=1;i<=n;i++)
41 {
42 fin>>d[i]>>w[i];
43 }
44 quicksort(w,1,n);
45 for(i=1;i<=n;i++)
46 {
47 if(d[i]>=n+1)
48 {
49 Max+=w[i];
50 continue;
51 }
52 for(j=d[i];j<=n;j++)
53 {
54 if(record[j]+1>j)
55 break;
56 }
57 if(j==n+1)
58 {
59 for(j=d[i];j<=n;j++)
60 record[j]++;
61 Max+=w[i];
62 }
63 }
64 for(i=1;i<=n;i++)
65 ans+=w[i];
66 ans-=Max;
67 fout<<ans<<endl;
68 }

  擬陣作為一種高級結構,是在貪心算法的研究中所必須掌握的,同時也由於它的難度較大,更需要我們來認真學習。

  更多關於擬陣的內容,請參見《算法導論(第二版)》的“貪心算法”一章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM