加工生产调度(流水作业调度问题)——Johnson算法应用

题目链接: link l i n k

从分析到解决

(从看题到放弃)

Step1 题意理解

简化下题目:

n n 个作业,在 M1, M2 M 1 ,   M 2 两台机器上完成。每个作业在 M1 M 1 上用时 a1 a 1 ,在 M2 M 2 上用时 b1 b 1 .且必须先在 M1 M 1 上加工。确定加工顺序,使得所有作业加工总时间最短。

也就是说,我们要做的是:确定顺序

Step2 分析算法

如何确定顺序,使得加工总时长最短 ?
我们的算法应当围绕它展开.

大胆思考策略,看看能否贪心地解决。

要使加工总时最短,就要使机器空闲的时间最短。一旦A机器开始加工,就要让A机器不停地作业,同理, B也应如此。

于是,可以得到如下所示的贪心策略:
要使得机器加工时间最短,就要让A先加工A加工的时间少的零件,让B能够尽快开工,也要使B最后加工B加工的时间少的零件,让A最后少等待一些。

Step3 解决问题

Si=min(ai, bi) S i = m i n ( a i ,   b i ) ,
然后, 对 S S 进行sort(从小到大),
接下去从1开始遍历 S S ,
如果Si = ai,则把它排到前面,否则排到后面。
这样,就完工了。

Step4 代码实现

#include

struct Str
{
  int w;
  int num;
};
int n;
int a[1010], b[1010];
Str s[5000];
int u, v;
int ans[1010];

bool cmp(Str x, Str y)
{
  return x.w < y.w;
}

int main(void)
{
  scanf("%d", &n);
  for(int k = 1;k <= n;k ++) scanf("%d", &a[k]);
  for(int k = 1;k <= n;k ++) scanf("%d", &b[k]);
  //读入

  for(int k = 1;k <= n;k ++) 
    s[k].w = std::min(a[k], b[k]), s[k].num = k;

  std :: sort(s+1, s+n+1, cmp);
  //结构体存储,s[k].w表示用的时间. s[k].num 表示其序号

  u = 0, v = n+1;
  for(int k = 1;k <= n;k ++)
    if(s[k].w == a[s[k].num])
      ans[++ u] = s[k].num;
    else
      ans[-- v] = s[k].num;
  //核心代码。也是我们刚刚讨论的算法的关键所在
  //ans数组存放的就是我们的最终处理序列

  u = 0, v = 0;
  for(int k = 1;k <= n;k ++)
  {
    u += a[ans[k]];

    if(v < u) v = u;
    v += b[ans[k]];
  }
  //统计用时.这里u表示a机器用时,v表示b机器用时,且每次v都被置为最大值.

  printf("%d\n", v);
  for(int k = 1;k <= n;k ++) printf("%d ", ans[k]);
  //输出

  return 0;
}

你可能感兴趣的:(算法笔记)