貪心算法實驗題


東 華 大 學

《算法分析設計與綜合實踐》實驗報告

 

學生姓名:曹晨學號:171310402 指導教師:章昭輝

實驗時間:2019-4-9 實驗地點:圖文信息大樓三號機房

 

  1. 實驗名稱

    貪心算法

  2. 實驗目的
    1. 理解貪心算法的概念。
    2. 掌握貪心算法的基本要素。
    3. 了解適用貪心算法的問題類型,並能設計相應的算法。
  3. 實驗內容
    1. 最優服務次序問題

      問題描述設有n個顧客同時等待一項服務,顧客i需要的服務時間為ti(1<=i<=n)。應如何安排n個顧客的服務次序才能使平均等待時間最小?平均等待時間是n個顧客等待服務時間的總和除以n。

      算法設計:對於給定的n個顧客需要的服務時間,計算最優服務次序。

      數據輸入:由文件input.txt提供輸入數據。第1行是正整數n,表示有n個顧客。接下來的1行中,有n個正整數,表示n個顧客需要服務的時間。

      結果輸出:將計算的最小平均等待時間輸出到文件output.txt。

    2. 非單位時間任務安排問題

      問題描述:具有截止時間和誤時懲罰的任務安排問題可描述如下

      1. 給定n個任務的集合S={1,2,….,n};
      2. 完成任務i需要ti時間,1<=i<=n;
      3. 任務i的截止時間di(1<=i<=n),即要求任務i在時間di之前結束
      4. 任務i的誤時時間wi(1<=i<=n),即任務i未在時間di之前結束,將招致wi的懲罰,若按時完成,則無懲罰。

        任務安排要求確定一個S的時間表(最優時間表)使得總誤時懲罰達到最小

      算法設計:對於給定的n個任務,計算總誤時懲罰最小的最優時間表

      數據輸入:由文件input.txt給出輸入數據。第1行是一個正整數n,表示任務數。接下來的n行中,每行有3個正整數a、b、c,表示完成相應任務需要時間a,截止時間為b,誤時懲罰值為c。

      結果輸出:將計算的總誤時時間輸出到文件output.txt。·

  4. 實驗過程
    1. 研究一個實例:有10個顧客,所需服務時間分別為56 12 1 99 1000 234 33 55 99 812

      用t[i]來表示每個顧客所需的服務時間,T[i]表示等待的時間。假設已知一個最優服務次序A={t(1),t(2),…t(n)};按照此順序每個顧客的等待時間為:T(1)=t(1),T(2)=t(1)+t(2),…….,T(n)=t(1)+t(2)+….+t(n);總的等待時間為sum=T(1)+T(2)+….+T(n);可以看出t(1)被加了n次, t(2)被加了n-1次,依此類推,直到t(n)被加一次后結束,除以n就等於平均等待服務時間。運用貪心策略,即最短服務時間優先。將t[i]按照遞增的順序排序,所得的序列就是最優服務序列。

顧客編號

1

2

3

4

5

6

7

8

9

10

服務時間

1

12

33

55

56

99

99

234

812

1000

等待時間

1

13

46

101

157

256

355

589

1401

2401

算法描述:

 

1 //求最短平均等待時間的函數

2 int Findbest(int *t,int n)//n是顧客的個數,t[n]用來存放每個顧客所需的服務時間

3 {

4 sort(t,t+n);//從小到大遞增排列數組t

5 int sum=0;//總的等待時間初始化0

6 for(int i to n)

7 sum+=t[i]*(n-i);//從1到n遍歷最優服務次序,並加上各個等待服務時間

8 sum=sum/n;//求平均等待服務時間

9 return sum;

10 }

 

  1. 定義一個結構體Task包含三項數據。

    struct Task

    {

    int a;//所需時間

    int b;//截止時間

    int c;//懲罰值

    };

    首先將任務按其截止時間遞增排序。假設對於任務1,2,…..,n,如果截至時間為d,則最小的誤時懲罰為p(i,d);

    其中p(i,d)={p(i-1,d)+t[i].c,p(i-1,min(d,t[i].a))}

    p(i-1,d)+t[i].c表示不做第i個任務時的誤時懲罰值,p(i-1,min(d,t[i].a))表示要做第i個任務時的誤時懲罰值,條件是必須在截止時間之前做完它。

    對於第一個任務,如果時間小於它完成時間,那么遭受懲罰,否則的話做第一個任務

    對於第i個任務,如果時間小於它的完成時間,不能執行,懲罰值等於上一個任務當前時間加上第i個任務的懲罰值,如果大於則比較不能完成時的懲罰值和完成這個任務所得的懲罰值,取二者最小的那個。下圖是一個實例的表。該例子為n=7;(1,4,70)(2,2,60)(1,4,50)(1,3,40)(1,1,30)(1,4,20)(3,6,80);

任務編號

截至時間0

1

2

3

4

5

6

0

30

0

0

0

0

0

0

1

90

60

30

30

30

30

30

2

130

90

60

30

30

30

30

3

200

130

90

60

30

30

30

4

250

180

130

90

60

60

60

5

270

200

150

110

80

80

80

6

350

280

230

190

160

150

110

 

算法描述:

1 //sort的自定義排序函數

2 bool comp(Task x,Task y)

3 {

4 if(x.b<y.b)//根據截至時間的大小進行非減排序

5 return true;

6 else return false;

7 }

8 //求最小懲罰值的函數

9 int Leastime(Task *t,int n)//t數組代表任務的三個參數,n代表任務的個數

10 {

11 sort(t,t+n,comp);//根據縮寫的comp函數排列數組(非減)

12 int d=t[n-1].b;//最大的截止時間d

13 int p[n][d+1];//二維數組p來代表p(i,d)時的最小懲罰數

14 memset(p,999,sizeof(p));//初始化數組

15 for(int i=0 to d)//遍歷二維數組的第一行,有時間做該任務,懲罰值為0,否則懲罰值為t[0].c

16 p[0][i]=(i>=t[0].a)?0:t[0].c;

17 for(int i=1 to n)//遍歷剩下的二維數組,

18 for(int j=0 to d)

19 p[i][j]=p[i-1][j]+t[i].c;//首先考慮不做當前任務的懲罰值

20 int h=t[i].b<j?t[0].b:j;//如果有時間做的話

21 if(h>=t[i].a&&p[i][j]>p[i-1][[h-t[i].a])//跟不做任務相比較

22 p[i][j]=p[i-1][h-t[i].a]//如果不做任務大於做任務的懲罰值,則做任務,改變p[i]j]的值

23 return p[n-1][d];//返回最小懲罰值

24 }

 

  1. 結果分析
    1. 答案是532

       

      這道題非常的簡單,用到了貪心算法的思路,通過短短幾步就能求解出答案。

      時間復雜度:一個for循環用來求總的等待服務時間

      F(n)=n=O(n)

      空間復雜度:一個一維數組t[n]用來存放各個顧客所需的服務時間

      F(n)=n =O(n);

    2. 答案是110

      這個題目是我覺得用動態規划的方法做出來的,因為有比較,做該任務和不做該任務的比較,貪心算法應該把兩種情況都寫入表中,但是只選了最優的方法

      時間復雜度:

      F(n)=n*logn+n*d=O(n*logn+n*d)

      空間復雜度:用一維結構體數組分別來存放該任務的三個屬性,一個二維數組用來存放在截止時間為d,i個任務的最小懲罰值

      F(n)=3*n+n*d=O(n+n*d);

  2. 實驗總結

附錄:(要求代碼里各行要有注釋

見打包文件

 


免責聲明!

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



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