实验题目:用贪心算法解决作业调度问题。
实验目的:
1. 学习带时限的作业调度—最大时限选择方法。
2. 掌握贪心算法的应用。
问题描述:
给定任务序列J1J2 ...Jn,假定只有一台处理机为这批作业服务。每件任务Ji给定一个时限di和对应利润Pi。只有在规定时限之内完成作业,才会得到利润Pi。通过设计合适的算法选择和安排任务子集Ji,使得J中的每个作业都能在各自的时限内完工,且使获得的利润∑Pi总和最大。
令d=max{di} 1≤i≤n,b=min{n,d}
任何最大利润的可完工子序列中的作业个数必不大于b。
解答方法:
1. 将任务按时限划分集合,时限按从大到小排列
令d=max{di} 1≤i≤n
2. 在时限为d的作业中选择一个利润最大的作业加入J
3. 在时限不小于d-1的作业中选择一个利润最大的作业加入J
4. 在时限不小于d-2的作业中选择一个利润最大的作业加入J
5. 如此进行下去,直到在时限不小于1的作业中选择利润最大的作业加入J。
预计输入输出
要求:依次输入任务序列J1J2 ...Jn各自对应时限di和对应利润Pi,要求输出最佳作业执行序列,使得获得的利润总和∑Pi最大,并输出最大利润总和。
按下表输入任务序列的参数:
任务Ji |
J1 |
J2 |
J3 |
J4 |
J5 |
J6 |
J7 |
时限di |
2 |
2 |
1 |
3 |
3 |
4 |
4 |
利润Pi |
20 |
15 |
20 |
5 |
1 |
10 |
20 |
预计输出:
作业执行序列为: J3→J1→J6→J7
最大利润为:70
不过这个算法对于N为10^5是超时的,TLE代码:
#include <cstdio> #include <algorithm> using namespace std ; const int maxn=100005; int p[maxn],d[maxn]; int rank[maxn],vis[maxn]; bool cmp (int a,int b) { return p[a]>p[b]; } int main () { int n,i,j; while (~scanf("%d",&n)) { int sum=0,maxd=0; memset (vis , 0 , sizeof(vis)); for (i=0 ; i<n ; ++i) { scanf("%d%d",p+i,d+i),rank[i]=i; if(d[i]>maxd)maxd=d[i]; } sort(rank,rank+n,cmp); int m=n; for (i=maxd ; i>0 ; --i) { for (j=0 ; j<n ; ++j) { if(!vis[rank[j]] && d[rank[j]]>=i) { sum+=p[rank[j]]; vis[rank[j]]=1; //printf("%d\t",j); break; } } } printf("%d\n",sum); } return 0; }
看了孔牛博客里的一个类似题目,利用了并查集,是个很诡异的算法,感觉根本不是人想的,看了10多分钟才明白代码的意思,
先将任务按利润即权值降序排序,然后从前到后一次将其加入到答案中,添加时构造个辅助数组f,存的是天数,当任务i被选择,
则让f[i]指向i-1。
AC代码 利用了辅助排序函数 时间上超越了孔牛 跑了0.33S
#include <cstdio> #include <algorithm> using namespace std ; const int maxn=100005; int p[maxn],d[maxn]; int rank[maxn],f[maxn]; bool cmp (int a,int b) { return p[a]>p[b]; } int find (int x) { return f[x]==x?x:f[x]=find(f[x]); } int main () { int n,i,j; while (~scanf("%d",&n)) { long long sum=0; int maxd=n;//maxd初始化为n for (i=0 ; i<n ; ++i) { scanf("%d%d",p+i,d+i); rank[i]=i; maxd>?=d[i]; } sort(rank,rank+n,cmp); for (i=0 ; i<=maxd ; i++)f[i]=i; for (i=0 ; i<n ; i++) { int father=find(d[rank[i]]); if(father) f[father]=father-1,sum+=p[rank[i]]; //printf("%d\t",father); } printf("%lld\n",sum); } return 0; }