今天训练做到一道题,发现居然有个算法:Johnson调度算法,觉得特别神奇!
流水调度问题的Johnson算法:
作业 i 需要走两步:先后进入A、B车间,各花费ai、bi时间,那么:
令N1={ i | ai < bi },N2={ i | ai >= bi };
将N1中作业按照ai的非递减排序,将N2中作业按照bi的非递增排序;
N1中作业和N2中作业相连接构成满足Johnson法则的最优调度。
以上摘自:http://blog.sina.com.cn/s/blog_7c35df9b0100vga3.html
即可理解为:
开始让第二台机器等的时间缩小
最后让第一台机器等的时间更小
好啦做题啦:
题目速递:http://poj.org/problem?id=2751
题意:有n项工作,各项工作需要经过车间A、车间B才ok。求如何安排时间最短。
根据上述算法,对工作做好安排后,计算花费时间即可。
(车间A无需等待谁,只需要自己有空就可以开干。而能进入车间B是只有那些已经经过车间A的才可以。)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
const int maxn=1e5+6;
const int inf=0x3f3f3f3f;
struct A{
int x,y;
}A1[maxn],A2[maxn];
bool cmp1(A a1,A a2){
if(a1.x==a2.x)
return a1.y<a2.y;
return a1.x<a2.x;
}
bool cmp2(A a1,A a2){
if(a1.y==a2.y)
return a1.x>a2.x;
return a1.y>a2.y;
}
int main(){
int n;
while((scanf("%d",&n)!=EOF)&&n){
int cnt1,cnt2;
cnt1=cnt2=0;
for(int i=0;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
if(x<y){
A1[cnt1].x=x;
A1[cnt1].y=y;
cnt1++;
}
else{
A2[cnt2].x=x;
A2[cnt2].y=y;
cnt2++;
}
}
sort(A1,A1+cnt1,cmp1);
sort(A2,A2+cnt2,cmp2);
int ans1,ans2;
ans1=ans2=0;
for(int i=0;i<cnt1;i++){
ans1+=A1[i].x;
if(ans2<ans1)
ans2=ans1+A1[i].y;
else
ans2+=A1[i].y;
}
for(int i=0;i<cnt2;i++){
ans1+=A2[i].x;
if(ans2<ans1)
ans2=ans1+A2[i].y;
else
ans2+=A2[i].y;
}
printf("%d\n",ans2);
}
}
说真的特别害怕这种问题,脑袋瓜子最受不住这类题目。。。想半天方法都是猜样例各种猜测。。。就怕码半天还猜错OMG