算法第二次作业

阅读: 评论:0

算法第二次作业

算法第二次作业

一、运行环境:

Win7、Dev-C++

二、运行过程说明:

数据文件格式:

  • 第一行是线路1上的各个装配站装配的时间;
  • 第二行是线路2上的各个装配站装配的时间;
  • 第三行是线路1上的装配站到线路2的(下一个)装配站的运输时间;
  • 第四行是线路2上的装配站到线路1的(下一个)装配站的运输时间 ;
  • 第五行是底盘分别到线路1和线路2的第一个装配站所需要的时间;
  • 第六行是线路1和线路2的最后一个装配站分别到达终点的市时间。

输入格式:输入测试数据集文件编号。

 

输出:

 

三、算法设计

3.1问题描述:

装配一辆汽车,有两条装配线分别有n个装配点,每条装配线在进出所花时间为e[i],x[i] (i=0,1),每个装配点所需时间a[i][j](i=0,1;j=0,1,...,n-1),从一条装配线i的第j个装配点到另一条装配线的第j+1个装配点所需时间t[i][j]。

 

3.2解题思路:

DP算法的设计可以分为四个步骤:描述最优解的结构;递归定义最优解的值;按自底而上的方式计算最优解的值;由计算出的结果创造一个最优解。

用上面的四步来解题:

  • 描述最优解的结构,即通过工厂最快路线的结构。
  • 递归定义最优解的值,计算最快时间。
  • 按自底而上的方式计算最优解的值,即计算最快时间。
  • 由计算出的结果创造一个最优解,构造通过工厂的最快路线。

 

3.3数据结构的选择:

  • 假设两条装配线都有n个装配站;
  • 最短时间int型f_star;
  • 最后出口的线路选择l_star(因为求出口时,要有个统一的入口,根据f1[n]+x1和f2[n]+x2的大小决定L*为1还是为2);
  • 每个装配站的最短时间使用整型二维数组f[2][n];
  • 到达i线上的j站点来自于哪个线上的j-1,使用整型二维数组l[2][n](l[i][j],其中i=1或2,j表示第j个装配站);
  • 每个装配站的装配时间使用整型二维数组a[2][n];
  • 每个装配站的运输时间使用整型二维数组t[2][n];
  • 底盘分别到达装配线1和装配线2的运输时间使用一维整形数组int e[2];
  • 装配线1和装配线2的最后一个装配站分别到达目的地的运时用一维整形数组int x[2];

四、算法详细描述:

4.1步骤以及伪代码:

(1)描述最优解的结构,即通过工厂最快路线的结构。

最后的出口(1,n)从第(1,n-1)位置或(2,n-1)来,出口(2,n)类似。这样一次划分后,具有最优子结构:一个问题的最优解包含了子问题的一个最优解。题中找出通过装配站S(i,j)的最优解,包含了找出通过S(1,j-1)或S(2,j-1)的一个最优解,通过S(1,j)的最快路线只能是以下两种选择:

通过配件站S(1,j-1),然后直接到达S(1,j);

通过配件站S(2,j-1),然后从装配线2到装配线1,最后到达S(1,j)。

问题转化为了,为解决该问题(寻找通过任一条装配线上的j的最快路线),解决其子问题(寻找通过两条装配线上的j-1的最快路线)来构造问题最优解。

(2)递归定义最优解的值,计算最快时间。

第一步分析了最优解是如何拆分的,第二步就是用来组成最优解。根据题意,写出f(i)与f(i-1)之间的关系。

先不考虑边界情况,得到如下递归式:

 

然后处理边界性问题(入口和出口):

出口时,应该求解f1[n]+x1,f2[n]+x2。然后选出其中的最小值求解。

入口条件如下:

 

因此得到两个方程组和一个结果方程

 

(3)按自底而上的方式计算最优解的值,即计算最快时间。

动态规划问题,采用自底向上的方式,需要建立数组来保持,防止递归带来的时间消耗,因此数组保存的是要递归时的返回值。也就是递归表达式中的f1[n-1]以及f2[n-2]。将i从1àn增长,一步一步求解。

计算最快时间的伪代码如下:

FAST_WAY ( a, t, e, x, n)1   f1[1] ße1 + a1,12   f2[1] ße2 + a2,13   for jß2 to n4             do if f1[j-1] + a1,j <= f2[j-1] + t2,j-1 + a1,j5                      then f1[j] ß f1[j-1] + a1,j6                               l1[j] ß 17                      else f1[j] ß f2[j-1] + t2,j-1 + a1,j8                               l1[j] ß 29             do if f2[j-1] + a2,j <= f1[j-1] + t1,j-1 + a2,j10                    then f2[j] ß f2[j-1] + a2,j11                             l2[j] ß 212                    else f1[j] ß f1[j-1] + t1,j-1 + a2,j13                             l2[j] ß 114 if f1[n] + x1 <= f2[n] + x215           then f* ßf1[n] + x116                    l* ß117           else f* ß f2[n] + x2l* ß 2

(4)由计算出的结果创造一个最优解,构造通过工厂的最快路线。

如果只需要最优解的话,不需要这一步。但如果需要给出方案,就需要数组保存路径信息。

构造通过工厂的最快路线的伪代码如下:

PRINT_STATIONS ( l , l* , n ) :iß l*print “line” i “, station” nfor j ß li[j]do I <- li[j]print “line” i “,station” j-1

4.2代码:

#include <stdio.h>int f[2][6]={0};    //对应通过各个装配站的最短时间int l[2][6]={0};    //对应通过各个装配站的来源int l_star;//记录选择的线路int f_star;//记录到达最短时间,/***         Dp求解 最短时间**         二维数组a 存储没个装配站装配时间*         二维数组t 存储装配站间的运输时间*         一维数组a 存储底盘运输到线路1的时间  和  运输到线路2的时间*         一维数组x 存储线路1最后一站运输到目的地的时间是   和   线路2最后一站运输到目的地的时间是2;*         n 每个线路拥有的装配站数量**  !!!:计算时间的同时要保持线路的纪录**/void Fastest_Way(int a[][6],int t[][5],int e[],int x[],int n){int j=0;f[0][0] = e[0]+ a[0][0];f[1][0] = e[1]+ a[1][0];for (j=1;j<n;j++)                          //自底向上开始计算f[i][j]的值,与l[i][j]的值{//对于在线路1的装配站来说if (f[0][j-1]+a[0][j] <= f[1][j-1]+t[1][j-1]+a[0][j])//选择第一条线 过来的{f[0][j] = f[0][j-1]+a[0][j];           l[0][j] = 0;}else//选择从第二条线过来的{f[0][j] = f[1][j-1]+t[1][j-1]+a[0][j];l[0][j] = 1;}//对于在线路2的装配站来说if (f[1][j-1]+a[1][j] <= f[0][j-1]+t[0][j-1]+a[1][j])//选择从第二条线过来的{f[1][j] = f[1][j-1]+a[1][j];l[1][j] = 1;}else//选择从第一条线过来得{f[1][j] = f[0][j-1]+t[0][j-1]+a[1][j];l[1][j] = 0;}  }if (f[0][5] + x[0] <= f[1][5] + x[1]){f_star = f[0][5]+x[0];              //  f_star为通过装配线的最短时间  l_star为产品最后出自哪个生产线l_star = 0;}else{f_star = f[1][5]+x[1];l_star = 1;}printf("运输最短时间为:%dn",f_star);}/***         根据记录得出最佳的路径 (根据站点顺序递归输出)*   *        二维数组l 记录了选择的线路l_star 和站点 n**/void Print_Station(int l[][6],int l_star,int n){  if ( n==0 )//边界条件return;l_star = l[l_star][n];/*递归*/Print_Station(l,l_star,n-1);printf("线路  %d ,  站点  %dn",l[l_star][n]+1,n);}int main(){FILE *fp;/*用户输入文件序号*/int index;printf("请输入文件序号(1-6)!");scanf("%d",&index);if(index>=1&&index<=6){char fname[100];//sprintf(fname,"%s%d%s","input_assgin02_0",index,".dat");puts(fname);/*读取数据文件 FILE * fopen(char *filename, char *mode);*/if ((fp=fopen(fname,"r"))==NULL){printf("文件读取失败!");return -1;}}int a[2][6];           //装配时间int t[2][5];           //运输时间int e[2];                         //底盘运输到线路1、线路2的时间int x[2];                        //线路1、线路2最后一站运输到目的地的时间int i=0,j=0;/*对每个站点的装配时间赋值 */printf("每个站点的装配时间n");for(i=0;i<2;i++){for(j=0;j<6;j++){fscanf(fp,"%d",&a[i][j]);printf("%dt", a[i][j]);}putchar('n');//每行结束换行}/*对站点两两之间的运输时间赋值*/printf("站点两两之间的运输时间n");for(i=0;i<2;i++){for(j=0;j<5;j++){fscanf(fp,"%d",&t[i][j]);printf("%dt", t[i][j]);}putchar('n');//每行结束换行}/*底盘运输到线路1、线路2的时间*/printf("底盘运输到线路1和线路2的运输时间n");for(i=0;i<2;i++){fscanf(fp,"%d",&e[i]);printf("%dt", e[i]);}putchar('n');/*终线路1、线路2最后一站运输到目的地的时间*/printf("线路1和线路2的最后一个装配站到目的地的运输时间n");for(i=0;i<2;i++){fscanf(fp,"%d",&x[i]);printf("%dt", x[i]);}putchar('n');/*求解最短时间*/Fastest_Way(a,t,e,x,6);/*求解最佳线路*/printf("运输最佳线路为:n");Print_Station(l,l_star,6);return 0;}

五、算法分析

动态规划由于从第二步开始每一步都利用上一步的结果来计算,从而避免了许多重复的计算,大大降低了时间复杂度。根据上面的工作方式,可以计算出时间复杂度为:O(n)。

空间复杂度:因为使用了二维数组、一维数组以及整型变量来保持记录,空间复杂度为:O(n)。

本文发布于:2024-01-28 11:04:39,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/17064110846971.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:作业   算法
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23