流水线调度dp问题

流水线调度 Assembly-Lines-Scheduling
问题:生产产品X需要经过m道手续,现在有两条流水线,每条流水线上m个站点,对应的站点功能相同, p[i][j]表示在第i条流水线上第j个站点上的加工时间;t[i][j]表示由第i条流水线跳转到第j条流水线上的时间。那么问题来了,想要用最短的时间加工完X,应该怎么加工呢?
分析:简单来讲,就是从1,1开始或者从2,1开始(哪条流水线开始),1,m结束还是2.m结束的问题,也就是最后只要比较cost[1][m]和cost[2][m]哪个比较小,比较无论如何要经过这m道工序
以1,m举例,到达1,m的时间cost[1][m]最小的话,有两种可能:一是经过流水线1,m-1然后不跳转直接到了1,m省了t[1][2]的时间; 另一种情况是本来再2,m-1的,结果发现从2上转过来再在1上加工最后一道程序比较快,也就是cost[2][m-1]+t[2][1]+p[1][m]分别表示在转过去之前已经消耗的时间和跳转流水线的时间和在1上完成最后一道工序的时间
所以只要找出min(cost[1][m], cost[2][m-1]+t[2][1]+ p[1][m])就可以了
那么问题来了cost[1][m]和cost[2][m-1]怎么知道呢
要知道cost[1][m]就得知道cost[1][m-1],就要知道cost[1][m-2]。。。就要知道
cost[1][1].幸运的是我们刚好就知道cost[1][1]和cost[2][1]就是p[1][1]和p[2][1]

所以这种有点递归性质的具有最优子结构的问题就可以使用动态规划来实现了
伪代码可以是这样的

cost[1][1]= p[1][1];
cost[2][1] = p[2][1];
for(int j = 2;j<=m;j++)
{

        cost[1][j] = min(cost[1][j-1]+p[1][j], cost[2][j-1]+t[2][1]+p[1][j]);
        cost[2][j] = min(cost[2][j-1]+p[2][j], cost[1][j-1]+t[1][2]+p[2][j]);

}

进一步呢可以推广到n条流水线的情况,每条流水线上m个站点的时候
其实这个时候就可以安静的用图里面的Floyd算法了

for(int i = 1;i<=n;i++)
for(int j = 1;j<=m;j++)
cost[i][j] = (1<<30);

for(int i = 1;i<=n;i++)
cost[i][1] = p[i][1];

for(int k = 2;k<=m;k++)//第k个站点
for(int i = 1;i<=n;i++)
for(int j = 1;j<=n;j++)
cost[i][k] = min(cost[i][k], cost[j][k-1]+t[j][1]+p[i][k]);

不过在最后的循环里改成

for(int k = 2;k<=m;k++)//第k个站点
for(int i = 1;i<=n;i++)
for(int j = 1;j<=n;j++)
{int temp = min(cost[i][k-1]+p[i][k], cost[j][k-1]+t[j][i]+ p[i][k]);
if(cost[i][k]>temp)
cost[i][k] = temp;
}

我真的找不到哪里不对,但是它确实不对……求指点……

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值