某汽车工厂有2个装配线,每个装配线有n个装配站(按顺序编号1~n),两个装配线对应的装配站执行相同的功能,但所用的时间可能不同.经过第i条流水线(i=1,2)的第j个装配站所花的时间为Aij。从第i条流水线的第j个装配站移到第j+1个装配站的时间可以忽略,而移到另外一个流水线的下一个装配站则需要一定的时间Tij。
汽车进入流水线不需要花时间,出流水线时需要花时间Tin。
汽车的装配需要按顺序经过所有装配站。
现在已知装配时间Aij和转移时间Tij,要求输出装配一辆汽车所需要的最短时间。
动态规划的算法思想
动态规划与贪心策略类似,将一个问题的解决方案视为一系列决策的结果。不同的是,贪心算法每采用一次贪心选择便做出一个不可撤回的决策,而在动态规划中,还要考察每个最优决策序列中是否包含一个最优决策自序列。使用动态规划时,所求的问题应具有以下两种性质:
最优子结构性质
所求问题的最优子结构性质是采用动态规划算法的条件之一,这种性质又被称为最优化原理。动态规划方法采用最优化原理来建立用于计算最优解的递归式。所谓最优化原理即不管前面的策略如何,此后的决策必须是基于当前状态(由上一次决策产生)的最优决策。由于对于有些问题的某些递归式来说并不一定能保证最优原则,因此在求解问题时有必要对它进行验证。若不能保持最优原则,则不可应用动态规划方法。在得到最优解的递归式之后,需要执行回溯以构造最优解。当最优决策序列中包含最优决策子序列时,可建立动态规划递归方程,它可以帮助我们高效的解决问题
子结构重迭性质
人们总希望编写一个简单的递归程序来求解动态规划方程。然而,如果不努力的去避免重复计算,递归程序的复杂性将非常可观。如果在递归程序设计中解决了重复计算问题,复杂性将大幅度下降。这种方法的思想是:由程序设置“备忘录”,每计算出一个新的子结构的解时,都保存起来。当遇到一次递归时,判断是否已经计算,如果已经计算,只需取出先前保存的结果即可。动态规划递归方程也可以用迭代方式来求解,这时很自然的避免了重复计算。尽管迭代程序与避免重复计算的递归程序有相同的重复性,但迭代程序不需要附加的递归栈空间,因此将避免重复计算的递归程序更快
装配线调度代码(c语言版)
#include
#include
#include
#define LINE 2
#define N 6
int main()
{
// 装配线装配时间
const int product[LINE][N] = {{7, 9, 3, 4, 8, 4}, {8, 5, 6, 4, 5, 7}};
// 装配线转移时间
const int transport[LINE][N - 1] = {{2, 3, 1, 3, 4}, {2, 1, 2, 2, 1}};
// 进装配线的时间
const int e1 = 2;
const int e2 = 4;
// 出装配站的时间
const int o1 = 3;
const int o2 = 2;
// 保存从起点到终点s(i, j)的最短时间
int final[LINE][N] = {{0}, {0}};
// 保存总时间
int time = 0;
// 保存经过路线
int line[LINE][N] = {{0}, {0}};
// 保存最后从哪条线走出装配线
int line_out = -1;
// 保存正序的最短装配路线
int path[N];
memset(path, -1, sizeof(path));
int i, j;
// 计算最快时间
final[0][0] = e1 + product[0][0];
final[1][0] = e2 + product[1][0];
for (j = 1; j < N; j ++) {
if (final[0][j - 1] + product[0][j] <= final[1][j - 1] + transport[1][j - 1] + product[0][j]) {
final[0][j] = final[0][j - 1] + product[0][j];
line[0][j] = 0;
}else {
final[0][j] = final[1][j - 1] + transport[1][j - 1] + product[0][j];
line[0][j] = 1;
}
if (final[1][j - 1] + product[1][j] <= final[0][j - 1] + transport[0][j - 1] + product[1][j]) {
final[1][j] = final[1][j - 1] + product[1][j];
line[1][j] = 1;
}else {
final[1][j] = final[0][j - 1] + transport[0][j - 1] + product[1][j];
line[1][j] = 0;
}
}
if (final[0][N - 1] + o1 <= final[1][N - 1] + o2) {
line_out = 0;
time = final[0][N - 1] + o1;
}else {
line_out = 1;
time = final[1][N - 1] + o2;
}
printf("总共花费的时间是:%d\n", time);
// 站号递增的顺序输出各装配站
for (j = N - 1, i = line_out; j >= 1; j --) {
i = line[i][j];
path[j] = i;
}
for (i = 1; i < N; i ++) {
printf("line: %d, station: %d\n", path[i] + 1, i);
}
printf("line: %d, station: %d\n", line_out + 1, N);
return 0;
}
最长公共子序列(LCS)
题目描述