問題&數據輸入&數據輸出:
分析:
首先將任務按其截止時間非減序排序。
對任務 1 , 2 , …… , i,如果截止時間為 d ,則最小誤時懲罰為 p( i , d ) 。
其中 p( i , d ) = min{ p(i-1, d)+wi , p(i-1, min{d, di}-ti) }
p(i-1, d)+wi 表示決定不做第 i 個任務,p(i-1, min{d, di}-ti) 表示決定要做第 i 個任務,這時必須在第 i 個任務的截至時間前做完它(即 min{d, di}-ti )
思路:
先將任務集按照結束時間非遞減排序。
設置數組p[ ][ ]來保存 p( i , d )的結果(本算法的局限性:時間只能為整數值)。
對於第一個任務來說,如果時間少於它需要執行的時間 t,則會遭受懲罰——p[1][ 0 ~ tasks[1].t ]=tasks[i].w;
時間夠則不然——p[1][ 0 - tasks[1].t ]=0。
對於第 i 個任務 的任務來說( i 取 2 - n),就如果時間少於它需要執行的時間 t,則不能執行它了,只能放棄——p[ i ][ 0 ~ tasks[1].t ]=p(i-1, d)+wi;
如果時間夠,則看是執行了好還是不執行好——p[ i ][ tasks[1].t ~ maxTime ] = min{ p(i-1, d)+wi , p(i-1, min{d, di}-ti) }。
代碼:
#include<iostream> #include<fstream> #define Max 99 using namespace std; struct Task { int t; //完成任務需要的時間 int d; //截止時間 int w; //誤時懲罰 }; void quickSort(Task s[], int l, int r) {//快速排序,不是重點 if (l < r) { int i = l, j = r; Task x = s[l]; while (i < j) { while (i < j && s[j].d >= x.d) j--; if (i < j) s[i++] = s[j]; while (i < j && s[i].d < x.d) i++; if (i < j) s[j--] = s[i]; } s[i] = x; quickSort(s, l, i - 1); quickSort(s, i + 1, r); } } int min(int a, int b) {return (a > b) ? b : a; } void main() { ifstream input("input.txt"); ofstream output("output.txt"); int n; input >> n; Task *tasks = new Task[n + 1]; for (int i = 1; i <= n; i++) { input >> tasks[i].t >> tasks[i].d >> tasks[i].w; } //按截至時間非遞減排序 quickSort(tasks, 1, n); int p[500][500]; //先初始化 for (int i = 1; i <= n; i++) { for (int j = 0; j < tasks[n].d; j++) { p[i][j] = Max; } } //任務 1,沒有更前面的任務了,單獨討論 for (int i = 0; i <= tasks[n].d; i++) { if (i < tasks[1].t)//如果沒給夠時間 { p[1][i] = tasks[1].w;//罰 } else { p[1][i] = 0; } } for (int i = 2; i <= n; i++) { for (int j = 0; j <= tasks[n].d; j++) { int a = p[i - 1][j] + tasks[i].w; int b = p[i - 1][min(j, tasks[i].d) - tasks[i].t]; if (j < tasks[i].t) { p[i][j] = a; } else { if (a < b) p[i][j] = a; else p[i][j] = b; } } } cout << p[n][tasks[n].d] << endl; cin >> n; input.close(); output.close(); }