★问题描述 有2个装配线,每一个装配线上有nSites个装配站,site[i][j]表示i个装配线上的j个装配站。两个装配线上相同位置的转配站有相同的功能。 在装配站site[i][j]上花费时间为assemTime[i][j]。进入和退出装配线i的时间分别为entranTime[i]和eixtTime[i].i=1,2 从一个装配站到相同装配线的下一个的时间忽略不计,到不同的装配站的时间为transTime[i][j]。 编一个程序,来确定在装配线1中选哪些站及在装配线2中选哪些站,使花费时间最短。 ★格式输入 第一行输入一个数字n,每条装配线上有n个装配站。 第二、三行各有2个数字,表示两条装配线进入、离开的时间。 第四、五行各有n个数字,表示两条装配线每个站点的装配时间。 第六、七行各有n-1个数字,表示两条装配线之间切换的时间。 ★格式输出 第一行1个数字,表示总的最短装配时间 第二行共n个数字,即经过的站点所在装配线的序号。 ★样例输入 6 2 3 4 2 7 9 3 4 8 4 8 5 6 4 5 7 2 3 1 3 4 2 1 2 2 1 ★样例输出 38 1 2 1 2 2 1 ★算法设计(包括算法设计过程中相关内容的说明、数据结构的选择、 算法详细描述及算法分析): ●1.设计说明: 1.1装配线调度问题具有最优子结构性质: 考虑子问题,汽车底盘从进厂到装配点site[i][j]的最短装配时间问题。假设最快的装配线路通过点 site[i][j],则有: (1)如果j=1,需要计算到达点assem[i][1]需要的时间 (2)如果j>1,到达点site[i][j]有两种方法: a)通过site[i][j-1]直接到达; b)通过另一条装配线的前一个装配点转移后到达。 通过点site[i][j]的最快装配路线是从进厂点经过路线p 再过点site[i][j-1]到达site[i][j], 则:从进厂到点site[i][j-1] 的装配路线p 也一定是从进厂点到点site[i][j-1]的最快装配路线。 1.2递推公式: fastTime[1][j] = assemTime[1][1] + exitTime[1]; //j==1; min{fastTime[1][j-1]+assemTime[1][j],fastTime[2][j-1]+transTime[2][j-1]+assemTime[1][j]}//j!=1; fastTime[2][j] = assemTime[2][1] + exitTime[2]; //j==1; min{fastTime[2][j-1]+assemTime[2][j],fastTime[1][j-1]+transTime[1][j-1]+assemTime[2][j]}//j!=1; ●2.算法设计: ●2.1数据结构: const int MAX_SITE = 1000; //允许装配点的最大数目 const string outFileName = "output.txt"; //输出文件名称 const int NLINE = 2; //装配线数 int nSites; //站点数 int assemTime[NLINE+1][MAX_SITE+1];//装配点装配时间 int transTime[NLINE+1][MAX_SITE]; //汽车从装配点site[i][j]传送到另一条装配线传送时间transTime[i][j] int line[NLINE+1][MAX_SITE+1]; //line[i][j]表示装配点site[i][j]前面一个装配点所在的装配线 int fastTime[NLINE+1][MAX_SITE+1]; //到装配点site[i][j]的最快装配时间 int lineLastSite; //最后一个装配点所在的装配线 int fastTimeSum; //最终的最快装配时间 int entranTime[NLINE+1]; //进入装配线时间 int exitTime[NLINE+1]; //退出装配线时间 int fastLine[MAX_SITE]; //记录最快装配线 ●2.2算法描述: void assemLineSchd() { Input(entranTime,exitTime,assemTime,transTime); //读文件输入数据 dAls(fastTime,assemTime,line,fastTimeSum,lineLastSite); //计算各装配线上各装配点的最短装配时间及前一个装配点所在装配线 getFastLine(lineLastSite,fastLine,line); //计算最快装配线 outputResult(fastTime,line,fastTimeSum,fastLine); //打印计算结果 } void dAls() { fastTime[1][j] = assemTime[1][1] + exitTime[1]; //j==1; min{fastTime[1][j-1]+assemTime[1][j],fastTime[2][j-1]+transTime[2][j-1]+assemTime[1][j]}//j!=1; fastTime[2][j] = assemTime[2][1] + exitTime[2]; //j==1; min{fastTime[2][j-1]+assemTime[2][j],fastTime[1][j-1]+transTime[1][j-1]+assemTime[2][j]}//j!=1; } ●2.3算法分析 本算法的最坏时间复杂度为:O(n) 最坏空间复杂度为:O(n) //============================================= //dAls.cpp //装配线调度问题,由input_assign02_XX.txt输入数据,将结果打印并输出至output.txt //动态规划解决Assembly line scheduling //递推公式fastTime[1][j] = | assemTime[1][1] + exitTime[1]; //j==1; // | min{fastTime[1][j-1]+assemTime[1][j],fastTime[2][j-1]+transTime[2][j-1]+assemTime[1][j]}//j!=1; // fastTime[2][j] = | assemTime[2][1] + exitTime[2]; //j==1; // | min{fastTime[2][j-1]+assemTime[2][j],fastTime[1][j-1]+transTime[1][j-1]+assemTime[2][j]}//j!=1; //by leo //04.01.2011 //============================================= #include<iostream> #include<algorithm> #include<fstream> #include<string> using namespace std; //--------------------------------------------- const int MAX_SITE = 1000; //允许装配点的最大数目 const string outFileName = "output.txt"; //输出文件名称 const int NLINE = 2; //装配线数 int nSites; //站点数 int assemTime[NLINE+1][MAX_SITE+1];//装配点装配时间 int transTime[NLINE+1][MAX_SITE]; //汽车从装配点site[i][j]传送到另一条装配线传送时间transTime[i][j] int line[NLINE+1][MAX_SITE+1]; //line[i][j]表示装配点site[i][j]前面一个装配点所在的装配线 int fastTime[NLINE+1][MAX_SITE+1]; //到装配点site[i][j]的最快装配时间 int lineLastSite; //最后一个装配点所在的装配线 int fastTimeSum; //最终的最快装配时间 int entranTime[NLINE+1]; //进入装配线时间 int exitTime[NLINE+1]; //退出装配线时间 int fastLine[MAX_SITE]; //记录最快装配线 //--------------------------------------------- void input(int* entranTime,int*exitTime,int assemTime[][MAX_SITE+1],int transTime[][MAX_SITE]); //读文件输入数据 void outputInitData(int* entranTime,int* exitTime,int assemTime[][MAX_SITE+1],int transTime[][MAX_SITE]); //打印初始化数据 void dAls(int fastTime[][MAX_SITE+1],int assemTime[][MAX_SITE+1],int line[][MAX_SITE+1],int& fastTimeSum,int& lineLastSite); //计算各装配线上各装配点的最短装配时间及前一个装配点所在装配线 void getFastLine(int lineLastSite,int* fastLine,int line[][MAX_SITE+1]); //计算最快装配线 void outputResult(int fastTime[][MAX_SITE+1],int line[][MAX_SITE+1],int fastTimeSum,int* fastLine); //打印计算结果 //-------------------------------------------- int main() { input(entranTime,exitTime,assemTime,transTime); outputInitData(entranTime,exitTime,assemTime,transTime); dAls(fastTime,assemTime,line,fastTimeSum,lineLastSite); getFastLine(lineLastSite,fastLine,line); outputResult(fastTime,line,fastTimeSum,fastLine); return 0; } //--------------------------------------------- //根据用户输入,读取相应文件内容并将之保存到数组中 //--------------------------------------------- void input(int* entranTime,int*exitTime,int assemTime[][MAX_SITE+1],int transTime[][MAX_SITE]) { string str; cout << "Please input the input file name(input_assign02_00.txt~input_assign02_10.txt):/n"; cin >> str; ifstream fin(str.c_str()); fin >> nSites; for(int i = 1; i <= NLINE; i++)//读进入和退出装配线的时间 { fin >> entranTime[i]; fin >> exitTime[i]; } for(int j = 1; j <= NLINE; j++)//读各装配点的装配时间 for(int k = 1; k <= nSites; k++) fin >> assemTime[j][k]; for(int m = 1; m <= NLINE; m++)//读转换装配线时的转换时间 for(int n = 1; n <= nSites -1; n++) fin >> transTime[m][n]; } //--------------------------------------------- //打印初始化数据 //--------------------------------------------- void outputInitData(int* entranTime,int* exitTime,int assemTime[][MAX_SITE+1],int transTime[][MAX_SITE]) { cout << "nSites: "<< nSites <<endl; for(int i = 1; i <= NLINE; i++)//打印进入和退出装配线的时间 { cout << "assembly line:" << i <<endl; cout << "entrance time: " <<entranTime[i] <<" "; cout << " exit time: " << exitTime[i] <<endl; } for(int j = 1; j <= NLINE; j++)//打印各装配点的装配时间 { cout << "assemble time of assembly line:" << j <<endl; for(int k = 1; k <= nSites; k++) cout << assemTime[j][k] <<" "; cout <<endl; } for(int m = 1; m <= NLINE; m++)//打印转换装配线时的转换时间 { cout << "transe time of assembly line:" << m <<endl; for(int n = 1; n <= nSites -1; n++) cout << transTime[m][n] << " "; cout <<endl; } } //--------------------------------------------- //计算各装配线上各装配点的最短装配时间及前一个装配点所在装配线 //--------------------------------------------- void dAls(int fastTime[][MAX_SITE+1],int assemTime[][MAX_SITE+1],int line[][MAX_SITE+1],int& fastTimeSum,int& lineLastSite) { fastTime[1][1] = entranTime[1] + assemTime[1][1]; fastTime[2][1] = entranTime[2] + assemTime[2][1]; for(int i = 2; i <= nSites; i++) { //计算装配线1上各装配点的最短装配时间及前一个装配点所在装配线 if(fastTime[1][i-1] + assemTime[1][i] < fastTime[2][i-1] + transTime[2][i-1] + assemTime[1][i]) { fastTime[1][i] = fastTime[1][i-1] + assemTime[1][i]; line[1][i] = 1; } else { fastTime[1][i] = fastTime[2][i-1] + transTime[2][i-1] + assemTime[1][i]; line[1][i] = 2; } //计算装配线2上各装配点的最短装配时间及前一个装配点所在装配线 if(fastTime[2][i-1] + assemTime[2][i] < fastTime[1][i-1] + transTime[1][i-1] + assemTime[2][i]) { fastTime[2][i] = fastTime[2][i-1] + assemTime[2][i]; line[2][i] = 2; } else { fastTime[2][i] = fastTime[1][i-1] + transTime[1][i-1] + assemTime[2][i]; line[2][i] = 1; } } //计算最短装配时间及最后装配点所在装配线 if(fastTime[1][nSites] + exitTime[1] < fastTime[2][nSites] + exitTime[2]) { fastTimeSum = fastTime[1][nSites] + exitTime[1]; lineLastSite = 1; } else { fastTimeSum = fastTime[2][nSites] + exitTime[2]; lineLastSite = 2; } } //--------------------------------------------- //计算最快装配线 //--------------------------------------------- void getFastLine(int lineLastSite,int* fastLine,int line[][MAX_SITE+1]) { fastLine[nSites] = lineLastSite; int lineKey = lineLastSite; for(int i = nSites; i > 1; i--) { lineKey = line[lineKey][i]; fastLine[i-1] = lineKey; } } //--------------------------------------------- //打印计算结果 //--------------------------------------------- void outputResult(int fastTime[][MAX_SITE+1], int line[][MAX_SITE+1],int fastTimeSum, int* fastLine) { ofstream fout(outFileName.c_str()); cout << "fastTime of sites :" <<endl; for(int i = 1; i <= 2; i++) { for(int j = 1; j <= nSites; j++) cout <<fastTime[i][j] << " "; cout<<endl; } cout << "line :" <<endl; for(int m = 1; m <= 2; m++) { for(int n = 2; n <= nSites; n++) cout <<line[m][n] << " "; cout <<endl; } cout <<endl << "fastTimeSum :" << fastTimeSum <<endl; fout << fastTimeSum <<endl; for(int k = 1; k <= nSites; k++) { cout << fastLine[k] << " "; fout << fastLine[k] << " "; } cout <<endl; } //=============================================