1. 程式人生 > >7-11 關鍵活動(30 分)

7-11 關鍵活動(30 分)

-h 兩個 tdi 最短 程序 lis 此外 開始 clu

7-11 關鍵活動(30 分)

假定一個工程項目由一組子任務構成,子任務之間有的可以並行執行,有的必須在完成了其它一些子任務後才能執行。“任務調度”包括一組子任務、以及每個子任務可以執行所依賴的子任務集。

比如完成一個專業的所有課程學習和畢業設計可以看成一個本科生要完成的一項工程,各門課程可以看成是子任務。有些課程可以同時開設,比如英語和C程序設計,它們沒有必須先修哪門的約束;有些課程則不可以同時開設,因為它們有先後的依賴關系,比如C程序設計和數據結構兩門課,必須先學習前者。

但是需要註意的是,對一組子任務,並不是任意的任務調度都是一個可行的方案。比如方案中存在“子任務A依賴於子任務B,子任務B依賴於子任務C,子任務C又依賴於子任務A”,那麽這三個任務哪個都不能先執行,這就是一個不可行的方案。

任務調度問題中,如果還給出了完成每個子任務需要的時間,則我們可以算出完成整個工程需要的最短時間。在這些子任務中,有些任務即使推遲幾天完成,也不會影響全局的工期;但是有些任務必須準時完成,否則整個項目的工期就要因此延誤,這種任務就叫“關鍵活動”。

請編寫程序判定一個給定的工程項目的任務調度是否可行;如果該調度方案可行,則計算完成整個工程項目需要的最短時間,並輸出所有的關鍵活動。

輸入格式:

輸入第1行給出兩個正整數N(100)和M,其中N是任務交接點(即銜接相互依賴的兩個子任務的節點,例如:若任務2要在任務1完成後才開始,則兩任務之間必有一個交接點)的數量。交接點按1~N編號,M是子任務的數量,依次編號為1~M。隨後M行,每行給出了3個正整數,分別是該任務開始和完成涉及的交接點編號以及該任務所需的時間,整數間用空格分隔。

輸出格式:

如果任務調度不可行,則輸出0;否則第1行輸出完成整個工程項目需要的時間,第2行開始輸出所有關鍵活動,每個關鍵活動占一行,按格式“V->W”輸出,其中V和W為該任務開始和完成涉及的交接點編號。關鍵活動輸出的順序規則是:任務開始的交接點編號小者優先,起點編號相同時,與輸入時任務的順序相反。

輸入樣例:

7 8
1 2 4
1 3 3
2 4 5
3 4 3
4 5 1
4 6 6
5 7 5
6 7 2

輸出樣例:

17
1->2
2->4
4->6
6->7

解題思路:這題基本上是基於拓撲排序的。此外還定義了一個最早發生時間的數組,從1循環到n;一個最遲發生時間,逆向循環

1 early[i] = FindMax( early[i],early[temp]+G[temp][i] );
2 
3 late[i] = FindMin( late[i],late[temp]-G[i][temp] );

這裏要註意的是最早發生時間是求幾個路線的最大數,最遲發生時間是求最小數

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 
  4 #define MAXVER 105
  5 #define INFINITY 65535
  6 
  7 int G[MAXVER][MAXVER];  //
  8 int early[MAXVER];      //最早發生時間
  9 int late[MAXVER];      //最遲發生時間
 10 int in[MAXVER];        //入度
 11 int out[MAXVER];       //出度
 12 int nv,ne;            //頂點數目 ,邊數目
 13 
 14 void CreatGraph();
 15 int EarlyTime();
 16 void LateTime(int Scost);
 17 int FindMax( int a,int b);
 18 int FindMin( int a,int b);
 19 
 20 int main()
 21 {
 22     int flag;
 23     int i,j;
 24     scanf("%d %d",&nv,&ne);
 25 
 26     CreatGraph();
 27     flag = EarlyTime();
 28     if( flag==-1)
 29     {
 30         printf("0\n");
 31     }
 32     else
 33     {
 34         printf("%d\n",flag);
 35         LateTime( flag );
 36         for( i=1; i<=nv; i++)
 37         {
 38             if(early[i] != late[i])
 39                 continue;
 40             for( j=nv; j>=1 ; j--)
 41             {
 42                 if( G[i][j]>=0 && early[j]==late[j] &&late[j]-G[i][j]==early[i])
 43                 {
 44                     //i,j均在關鍵路徑上且相鄰
 45                     printf("%d->%d\n",i,j);
 46                 }
 47             }
 48         }
 49 
 50     }
 51     return 0;
 52 }
 53 
 54 void CreatGraph()
 55 {
 56     int i,j;
 57     int s,d,cost;
 58 
 59     for( i=1; i<=nv; i++)
 60     {
 61         for( j=1; j<=nv; j++)
 62         {
 63             G[i][j] = -1;
 64         }
 65         early[i] = 0;
 66         late[i] = INFINITY;
 67         in[i] = 0;
 68         out[i] = 0;
 69     }
 70     for( i=0; i<ne; i++)
 71     {
 72         scanf("%d %d %d",&s,&d,&cost);
 73         G[s][d] = cost;   //有向邊
 74         in[d] ++;
 75         out[s]++;
 76     }
 77 
 78 }
 79 
 80 int EarlyTime()
 81 {
 82     int queue[nv];
 83     int first =-1,rear = -1;
 84     int count=0;
 85     int i;
 86     int temp,ret=0;
 87 
 88     for( i=1; i<=nv; i++)
 89     {
 90         if( in[i]==0)
 91         {
 92             //如果入度為0則入隊
 93             queue[++rear] = i;
 94         }
 95     }
 96 
 97     while( first<rear)    //判斷隊是否為空
 98     {
 99         temp = queue[++first];   //出隊
100         count++;
101         for( i=1; i<=nv; i++)
102         {
103             if( G[temp][i]>=0 )
104             {
105                 in[i]--;
106                 early[i] = FindMax( early[i],early[temp]+G[temp][i]);
107                 if( in[i]==0)
108                 {
109                     queue[++rear] = i;
110                 }
111             }
112         }
113     }
114     if( count!=nv)
115     {
116         ret = -1;
117     }
118     else
119     {
120         ret = early[1];
121         for( i=2; i<=nv; i++)
122         {
123             if(early[i] > ret)
124             {
125                 //找出最大的early[i]
126                 ret = early[i];
127             }
128         }
129     }
130 
131     return ret;
132 }
133 
134 void LateTime(int Scost)
135 {
136     int i;
137     int queue[MAXVER];
138     int first=-1,rear=-1;
139     int temp;
140 
141     for( i=1; i<=nv; i++)
142     {
143         if( out[i]==0)
144         {
145             queue[++rear] = i;
146             late[i] = Scost;
147         }
148     }
149 
150     while( first<rear )
151     {
152         temp = queue[++first];
153         for( i=nv; i>=1; i--)
154         {
155             if( G[i][temp]>=0)
156             {
157                 late[i] = FindMin( late[i],late[temp]-G[i][temp]);
158                 out[i]--;
159                 if(out[i]==0)
160                 {
161                     queue[++rear] = i;
162                 }
163             }
164         }
165 
166     }
167 
168 }
169 int FindMax( int a,int b)
170 {
171     if( a>b )
172     {
173         return a;
174     }
175     else
176     {
177         return b;
178     }
179 }
180 int FindMin( int a,int b)
181 {
182     if( a>b )
183     {
184         return b;
185     }
186     else
187     {
188         return a;
189     }
190 }

PS:作為一個剛剛接觸的渣渣,我覺得這道題有點難,做了很久,實在沒思路的話就跳過吧




7-11 關鍵活動(30 分)