任务调度问题1—贪心算法
2012-10-12 18:50 kliner 阅读(8009) 评论(0) 编辑 收藏 举报这个问题是《算法导论》上的一个经典的贪心算法问题——单处理器上具有期限和惩罚的单位时间任务调度问题,目标是使惩罚最小。
输入:第一行一个数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 }
拟阵作为一种高级结构,是在贪心算法的研究中所必须掌握的,同时也由于它的难度较大,更需要我们来认真学习。
更多关于拟阵的内容,请参见《算法导论(第二版)》的“贪心算法”一章。