对于加工顺序相同的两个或两个以上作业在两台机器上的加工排序,称之为:n个作业两台机床的作业排序问题,经典的启发式排序方法为Johnson规则。
思路:
先构成生产周期最短的最优作业顺序:
1.把作业分为两类,
A类 : 第一个花的作业的时间< 第二个花的作业的时间
B类 : 第一个花的作业的时间>= 第二个花的作业的时间
2.排序
对A类进行排序:按第一个花的作业的时间从小到大
对B类进行排序:按第二个花的作业的时间从大到小
3.合并
把A类B类作业合并即为生产周期最短的最优作业顺序
#include<stdio.h> #include <iostream> #include <algorithm> using namespace std; #define max_v 50005 struct node{ int x,y,i; }p[max_v],pp[max_v]; bool cmp1(node a,node b){ return a.x<b.x; } bool cmp2(node a,node b){ return a.y>b.y; } int main() { int n; while(~scanf("%d",&n)){ int len1=0,len2=0; int x,y; for(int i=0;i<n;i++){ scanf("%d %d",&x,&y); if(x<y){ p[len1].x=x; p[len1].i=i+1;//第几个作业 p[len1++].y=y; } else{ pp[len2].x=x; pp[len2].i=i+1;//第几个作业 pp[len2++].y=y; } } sort(p,p+len1,cmp1); sort(pp,pp+len2,cmp2); for(int i=len1;i<len1+len2;i++){ p[i]=pp[i-len1]; } cout<<"输出他们作业的顺序:"<<endl; for(int i=0;i<len1+len2;i++) cout<<p[i].i<<" "; cout<<endl; int sum=p[0].x; int res=p[0].x+p[0].y; for(int i=1;i<n;i++) { sum+=p[i].x; res=max(res,sum)+p[i].y; } cout<<"输出他们最少所用的时间:"<<endl; printf("%d\n",res); } return 0; }
#include<stdio.h> #include <iostream> #include <algorithm> using namespace std; #define max_v 50005 struct node{ int x,y,i; }p[max_v],pp[max_v]; bool cmp1(node a,node b){ return a.x<b.x; } bool cmp2(node a,node b){ return a.y>b.y; } int main() { int n; while(~scanf("%d",&n)){ int len1=0,len2=0; int x,y; for(int i=0;i<n;i++){ scanf("%d %d",&x,&y); if(x<y){ p[len1].x=x; p[len1].i=i+1;//第几个作业 p[len1++].y=y; } else{ pp[len2].x=x; pp[len2].i=i+1;//第几个作业 pp[len2++].y=y; } } sort(p,p+len1,cmp1); sort(pp,pp+len2,cmp2); for(int i=len1;i<len1+len2;i++){ p[i]=pp[i-len1]; } // cout<<"输出他们作业的顺序:"<<endl; // for(int i=0;i<len1+len2;i++) // cout<<p[i].i<<" "; // cout<<endl; int sum=p[0].x; int res=p[0].x+p[0].y; for(int i=1;i<n;i++) { sum+=p[i].x; res=max(res,sum)+p[i].y; } // cout<<"输出他们最少所用的时间:"<<endl; printf("%d\n",res); } return 0; }
动态规划的思想:
https://blog.csdn.net/huang1600301017/article/details/81022658
贪心算法训练:
https://www.cnblogs.com/NikkiNikita/p/9458496.html
https://blog.csdn.net/qq_39382769/article/month/2018/07/1?
思路:Johnson算法:
1:将任务分为两类,A类任务t1<t2,B类任务t1>=t2
2:两类任务分别排序,其中A类按 t1 递增排序,B类按 t2 递减排序
3:合并两类,将第二类任务接到第一类任务后面,此时任务的顺序最佳
4:遍历所有任务,计算总耗时
说下我的理解,对于 t1作业来说肯定是一直运行的,那么对于 t2 作业则会有 空闲和堆积两种境况,按照最小耗时,显然是不允许出现空闲情况的,因此 要先将 作业中 t1<t2的 按照 t1递增的顺序执行,这样便不会出现空闲情况,对于 剩余作业中就是 t1 >=t2的作业了,此时t2作业还处于堆积情况中,当每执行一个作业,由于 t1>=t2,t2作业中堆积的作业耗时会越来越小,因此要先将 t2较大的先执行,否则t2较大的滞留在最后便会增加耗时,因此再将 t1>=t2的作业按照 t2递减的顺序执行,如此便为最小耗时。
/* Johnson算法: 1:将任务分为两类,A类任务t1<t2,B类任务t1>=t2 2:两类任务分别排序,其中A类按 t1 递增排序,B类按 t2 递减排序 3:合并两类,将第二类任务接到第一类任务后面,此时任务的顺序最佳 4:遍历所有任务,计算总耗时 */ #include<iostream> #include<algorithm> using namespace std; typedef long long LL; struct node { int time; int id; bool group; bool operator<(const node &p){ return time<p.time; } }; const int MAX_N=50005; int n; int a[MAX_N],b[MAX_N]; node d[MAX_N]; int best[MAX_N]; int main() { ios::sync_with_stdio(false); cin>>n; for(int i=0;i<n;i++) cin>>a[i]>>b[i]; for(int i=0;i<n;i++){ d[i].time=a[i]>b[i]?b[i]:a[i]; d[i].id=i; d[i].group=a[i]<=b[i]; } sort(d,d+n); int l=0,r=n-1; for(int i=0;i<n;i++) if(d[i].group) best[l++]=d[i].id; else best[r--]=d[i].id; LL sum=0,ans=0; for(int i=0;i<n;i++) { sum+=a[best[i]]; ans=max(ans,sum)+b[best[i]]; } cout<<ans<<endl; // for(int i=0;i<n;i++) // printf("%d ",best[i]+1); // printf("\n"); return 0; }