最小重量机器设计问题+工作分配问题
(完整word版)最小重量机器设计问题
最小重量机器设计问题1。
问题描述设某一机器由n个部件组成,每一个部件都可以从m个不同的供应商处购得。
设wij是从供应商j处购得的部件i的重量,cij是相应的价格。
试设计一个算法,给出总价格不超过c的最小重量机器设计.算法设计:对于给定的机器部件重量和机器部件价格,计算总价格不超过d的最小重量机器设计。
2.算法流程分析设开始时bestx=[-1,—1,…,—1]则相应的排列树由x[0:n—1]的所有排列构成。
找最小重量机器设计的回溯算法Backtrack是类machine的公有成员。
私有数据成员整型数组Savex保存搜索过的路径,到达叶节点后将数据赋值给数组bestx。
成员bestw记录当前最小重量,cc表示当前花费,cw表示当前的重量。
在递归函数Backtrack中,在保证总花费不超过c的情况下:当i=n时,当前扩展结点是排列树的叶节点。
此时搜索到一个解,判断此时的最小重量是否小于当前最小重量,若小于则更新bestw, 并得到搜索路径bestx.当i〈n时,当前扩展结点位于排列树的第i—1层.当x[0:i]的花费小于给定最小花费时,算法进入排列树的第i层,否则将减去相应的子树。
算法用变量cc记录当前路径x[0:i]的费用。
3。
算法正确性证明通过几组实例证明合法的输入可以得到正确的输出.实例见附录第2部分。
4.算法复杂度分析时间复杂度是O(n2)5.参考文献[1] 王晓东编著,计算机算法设计与分析(第4版)。
北京:电子工业出版社,2012。
26。
附录(1)可执行代码如下:#include<iostream〉using namespace std;#define N 50class MinWmechine{int n; //部件个数int m;//供应商个数int COST; //题目中的Cint cw; //当前的重量int cc;//当前花费int bestw; //当前最小重量int bestx[N];int savex[N];int w[N][N];int c[N][N];public:MinWmechine();void machine_plan(int i);void prinout();};MinWmechine::MinWmechine(){cw=0; //当前的重量cc=0; //当前花费bestw=-1;//当前最小重量bestx[N];savex[N];cout<<”请输入部件个数:";cin〉〉n;cout〈〈”请输入供应商个数:"; cin>〉m;cout<<”请输入总价格不超过:"; cin>〉COST;for(int j=0;j<m;j++){for(int i=0;i〈n;i++)cout〈〈"请输入第"〈〈j+1〈<" 个供应商的第"〈〈i+1<〈”个部件的重量:”;cin>>w[i][j];cout〈〈”请输入第”〈<j+1〈<”个供应商的第”〈<i+1<<”个部件的价格:";cin〉>c[i][j];if(w[i][j]〈0 ||c[i][j]<0){cout〈<"重量或价钱不能为负数!\n";i=i—1;}}}}void MinWmechine::machine_plan(int i){if(i>=n){if(cw 〈bestw || bestw==—1){bestw=cw;for(int j=0;j〈n; j++) //把当前搜过的路径记下来savex[j]=bestx[j];return;}for(int j=0; j<m; j++)//依次递归尝试每个供应商{if(cc+c[i][j]〈COST){cc+=c[i][j];cw+=w[i][j];bestx[i]=j;machine_plan(i+1);bestx[i]=-1;cc-=c[i][j];cw—=w[i][j];}}}void MinWmechine::prinout(){int i,j,ccc=0;for(j=0;j〈m;j++){for(i=0;i〈n;i++){cout<〈"第”<<j+1〈<”供应商的第”<〈i+1〈〈”部件重量:”<〈w[i][j]〈〈" 价格:"<〈c[i][j]<<"\n”;}}for(j=0; j<n; j++){bestx[j]=-1;}machine_plan(0);cout<<”\n最小重量机器的重量是:"〈<bestw〈〈endl;for(int k=0;k〈n;k++){cout<<" 第"〈〈k+1〈〈" 部件来自供应商”〈<savex[k]+1<〈"\n”;ccc+=c[k][savex[k]];}cout〈〈"\n该机器的总价钱是: "<〈ccc<<endl;cout〈<endl;}int main(void){MinWmechine Y;Y。
机械机床分配问题
任务分配到机床摘要本文解决的是在不同加工要求下,机床加工过程中的任务分配问题,属于组合优化问题。
为解决此问题,我们运用数学中的约束规划与整数规划的混合方法[1] ,建立起最优化模型。
针对问题一:本文首先根据机床工作时间定义机床任务量均衡度,均衡度越小,各机床任务量越均衡。
由于不同产品加工任务量、可用机床不同,本文将整数规划作为主问题解决机器的分派问题,将约束规划作为子问题解决任务在机床上加工的排序问题。
然后确立两个目标函数:最短完成订单时间,最小均衡度。
最后根据确立的这两个目标建立起双目标最优化模型,运用lingo软件编程得到完成订单的最短时间为270小时,机床任务量均衡度为1.4%,各机床任务分配见5.3表二,各机床完成加工时间如下表:机床1机床2机床3机床4机床5机床6 230小时259小时231小时231小时267小时270小时针对问题二:本文在解决问题一的基础上,将机床的加工时间作为变量1,将产品在机床间的调度次数作为变量2,并以机床运行费用和调度费用确立的总生产费为目标函数,建立起单目标最优化模型,运用lingo软件编程得到最小总生产费用为202.75万元,各机床任务分配见6.3表四,各机床加工费用和调度总费用如下表:机床机床1 机床2 机床3 机床4 机床5 机床6 调度费用总费用费用(万)45.4 41.58 34.65 27.72 23 18.4 12 202.75 最后我们针对实际情况,对模型进行了改进,改进后的整数规划与约束规划模型使机床加工调度问题更接近实际,此时得出的分配方案更优。
关键字:约束规划整数规划车间作业调度一问题重述1.1问题背景在制造企业的中期或短期生产计划管理中,常常要考虑到如下的生产计划优化问题:在给定的外部需求和生产能力等限制条件下,按照一定的生产目标(生产总时间最小、生产总费用最小)编制未来若干个生产周期的最优生产计划。
1.2该工厂机床加工各种产品相关信息某工厂收到了5个客户提交的5种不同的加工任务订单,5个客户的任务订单量分别为 8,13,7,12,5。
优先队列最小重量机器设计问题
4.代ቤተ መጻሕፍቲ ባይዱ:
最小重量机器设计问题
1.问题描述:
设某机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设 是从供应商j处购得的部件i的重量, 是相应的价格。设计一个优先队列式分支限界法,给出总价格不超过d的最小重量机器设计。
2.算法设计
问题的解空间为一棵排列树,采用优先队列式分支限界法找出所给的最小重量机器设计。开始时,将排列树的根节点置为当前扩展结点。在初始扩展结点处还设有选定部件是哪个供应商提供的,故level=0,source=0,value=0,weight=0。MinLeaf记录满足条件的节点即供应商的选择。while完成对排列树内部结点的有序扩展。循环体内依次从活结点优先队列中取出具有最小重量的结点,依次为当前扩展结点。并且花费不超过d并加以扩展,队列为空时则结束循环。当fartherNode->level等于n时,此时扩展结点是叶节点,判断是否最优,若最优则记录节点。当fartherNode->level<n时,算法依次产生当前扩展结点的所有儿子节点。对于当前扩展结点的一个儿子结点,计算出当前的重量,当小于当前的最小重量时,将儿子结点插入到活结点优先队列中,而当不下于当前最小重量时,以当前这个结点为根的子树中不可能有比当前最小重量部件选择更好的解,故可将此结点舍去。若在一结点所计算的花费大于所给的最小花费,则剪去以此节点为根的子树。
《算法设计》课程报告--最小重量机器设计问题-新版.pdf
m个
不同的供应商处购得。高
wij 是从供应商 j 处购得的部件 i 的重量,
cij 是相应的价格。
试设计一个算法,给出总价格不超过
c 的最小重量机器设计。
编程任务: 对于给定的机器部件重量和机器部件价格,编程计算总价
格不超过 d 的最小重量机器设计。 数据输入:由文件 input.txt 给出输入数据。第一行有
-2-
课程名称:
学生姓名:
学生学号:
if(t>n){
if(cur_minWeight < minWeight){//
保存最优解和最优值
minWeight = cur_minWeight;
for(int r=1;r<=n;++r){
solution[r] = cur_solution[r];
}
}
}
else{
for(int i=1;i<=m;++i){
d -= c[t][i];
cur_solution[t] = i;
cur_minWeight += w[t][i];
if(d>=0) {
Backtrack(t+1,n,m,d);
}
cur_minWeight -= w[t][i];
//if(Constraint(t) && Bound(t)) Backtrack(t+1,n,m,d);
}
return 0;
}
分支定界法代码
#include <stdio.h>
#include <stdlib.h>
#include <list>
最小重量机器设计问题
问题描述
最小重量机器设计问题: 设某一机器由n个部件组成,每一种部 件可以从m个不同的供应商处购得。设wij 是从供应商j处购得的部件i的重量,cij是相 应的价格。 试设计一个算法,给出总价格不超过c 的最小重量机器设计。
算法设计:对于给定的机器部件重量和机 器部件价格,计算总价格不超过d的最小重 量机器设计。 数据输入:由文件input.txt给出输入数据。 第一行有3个正整数n,m和d。接下来的2n 行,每行n个数。前n行是c,后n行是w。 结果输出:将计算的最小重量及每个部件 的供应商输出到文件output.txt。
ห้องสมุดไป่ตู้
2. 每一个零件的最后一个商家已经被考虑过,返回 上一个零件的选择。 其中对于最后一个零件,一旦商家的零件型号被 选中,比较已经记录的最优总重量与该采购清单的总 重量,如果比最优总重量要小,更改最优采购清单及 最优总重量,不再进入下一个零件的选择。 对于第一个零件,当其所有商家都已被考虑后, 就终止。 这里使用i表示正在选择第i个零件,使用a[i]表示 第i个零件选择的商家,i++和i--表示递进或回溯,由 于最后判断终止条件时需要判断第一个零件选择到了 最后一个商家时,是不是从下层回溯回来的,如果是, 则终止,否则,则是第一个零件选择了最后一个商家, 而且将要进入下面的零件的选择,所以使用bool型变 量direction表示是否是回溯(false表示由下一层回溯)。
算法思想
本题的实质是在解析空间进行搜索,进行深度优先搜索, 但是为了节省空间与时间资源,使用数组以及条件判断来 模拟基于深度优先的回溯法。 对于搜索中的每一步,有如下情况: 1.不是最后一个零件还没有考虑完所有商家,选择每一 个零件的商家不是最后一个商家,只有两种情况,该商家 的零件型号符合要求(即包括该零件,已经选择的零件总 价格没有超过价格上限),则确定该零件选择该商家,并 进入下一个零件的选择,或者该商家的零件型号不符合要 求,跳过该商家,该零件开始选择下一个商家。
5.4 最小重量机器设计问题
5.4 最小重量机器设计问题算法设计思想:这是最优规划问题,采用回溯法求解。
用动态数组存放选购方案,通过递归函数进行零件的搜索和方案的剪枝,最终得到最小重量的机器零件选购方案。
递归函数void Search(int i, int s, int l, int *e)有4个参数:1.i是搜索的起点,初始从i=1(第一个零件)开始,满足条件i==n+1时表示找到一种选购方案,作为递归的结束条件;2.s是当前重量,也是规划目标。
题目要找最小重量的机器,因此设置一个min,每次找到一个选购方案时比较s,保留较小的。
另外,在搜索的过程中,判断条件s>min,一旦成立,说明已经不可能是最优解,即可进行剪枝。
3.l是当前价格,题目要求机器的总价格不超过d,因此l<d是规划的约束条件。
4.*e是当前选购方案,存储已经选出的零件。
当递归达到结束条件,且满足重量和价格要求时,e中存放了一种更优的选购方案,于是更新选购方案*plan。
整个程序搜索完成之后,*plan中存放的即使整体的最优选购方案。
该算法重点是控制递归过程的参数变化,递归的结束条件和优化剪枝方法。
另外,程序有一定的鲁棒性,对非法输入和文件错误进行了检测。
程序设计代码:/*头文件最小重量机器设计问题.h*/#ifndef KNAP_H#define KNAP_H#include <iostream>#include <fstream>using namespace std;class Machine //机器类{public:Machine(char *in, char *out); //构造函数~Machine(); //析构函数void Solve(); //输出结果到文件protected:void Search(int i, int s, int l, int *e); //从第i个部件开始递归搜索void Print(); //输出结果private:int n; //部件个数int m; //供应商个数int d; //价格上限int **w; //部件重量int **c; //部件价格int min; //最小重量int *plan; //选购的部件ofstream fout; //输出结果文件};#endif/*函数实现文件最小重量机器设计问题.cpp*/#include "最小重量机器设计问题.h"Machine::Machine(char *in, char *out) : fout(out){ifstream fin(in);if( !fin ){cerr << "文件" << in << "无法打开!" << endl;exit(1);}fin >> n >> m >> d; //初始化部件个数n,供应商数m,价格限制d w = new int*[n+1];for(int i = 1; i <= n; i++){w[i] = new int[m+1];for(int j = 1; j <= m; j++)fin >> w[i][j]; //初始化部件重量}c = new int*[n+1];for(int i = 1; i <= n; i++){c[i] = new int[n+1];for(int j = 1; j <= m; j++)fin >> c[i][j]; //初始化部件价格}fin.close();min = INT_MAX; //初始化最小重量plan = new int[n+1];for(int i = 1; i <= n; i++)plan[i] = 0; //初始化选购计划if( !fout ){cerr << "文件" << out << "无法打开!" << endl;exit(1);}}Machine::~Machine(){if(fout)fout.close();for(int i = 1; i <= n; i++){if(w[i])delete[] w[i];if(c[i])delete[] c[i];}if(w)delete[] w;if(c)delete[] c;}void Machine::Solve(){int *e;e = new int[n+1];for(int i = 1; i <= n; i++)e[i] = 0;Search(1, 0, 0, e); //第一个零件开始搜索,初始重量和价格是0 Print(); //输出函数}void Machine::Search(int i, int s, int l, int *e){if(i == n+1) //选购完毕{if(s < min && l <= d) //找到一个更优解{min = s; //更新重量最小值for(int i = 1; i <= n; i++)plan[i] = e[i]; //更新选购计划}return;}if(s > min) //重量超过min,剪枝return;for(int j = 1; j <= m; j++){e[i] = j;s += w[i][j]; //加上第i部件由j供应商提供的重量l += c[i][j]; //加上第i部件由j供应商提供的价格Search(i+1, s, l, e); //递归选购下一个部件s -= w[i][j];l -= c[i][j];}}void Machine::Print(){fout << min << endl;for(int i = 1; i <= n; i++)fout << plan[i] << ' ';}/*主函数文件test.cpp*/#include "最小重量机器设计问题.h"int main(){char *in = "input.txt"; //输入文件char *out = "output.txt"; //输出文件Machine machine(in, out); //文件初始化机器machine.Solve(); //回溯法求解return 0;}。
机床任务分配问题数学建模
任务分配到机床摘要本文解决的是机床生产调度的问题,目的是使产品加工路径的组合优化。
对于本文所研究的机床任务的合理调度问题,由于生产方式的不确定,我们根据A,B,C,D这4道工序是否有序进行了分类研究,并分情况得到了最优解或近似最优解,制定出了不同情况下的合理调度方案。
对于问题一:在工序无序的情况下,问题转化为一个指派问题,以完成任务耗时最长的那台机床的运行时间作为指标,以该指标最小作为目标函数,建立了一个0-1整数规划模型,用Lingo求解得最短加工时间为233h各机床加工时间的均衡度为3.8%。
在工序有序的情况下,问题一转化为一个柔性作业车间调度问题,此时生产调度的任务就是:确定产品的加工路径和每一工序的加工开始时间,并使产品通过系统的时间(Makespan)最小。
运用遗传算法建立模型,绘制出最佳调度的甘特图,并得到加工时间的近似最优解为250h,各机床加工时间均衡度为1.6%,均衡度很高;与无序情况所得最优解相比,其近似度为92.7%,具有较好的有效性。
对于问题二:在工序无序的情况下,该问题仍为一个指派问题,在加入调度费用与运行费用的条件下,我们利用理想点法将这两个指标的双目标问题转化为单目标规划模型来进行求解,建立了一个0-1整数规划模型,用Lingo求解得加工时间为510h,总费用为1784600元。
在工序有序的情况下,我们运用蚁群算法建立模型,经过选工序,计算加工工序k的机床的空闲时间段和加工序列,计算可选工序的EAPT和信息素的积累等过程,得到加工时间为441h,总费用为1799000元。
为了进一步分析该算法的有效性,我们还进行了实例规模较大的计算机仿真试验。
我们在模型的改进和推广里对模型四提出了一种评价方法,力求使一群算法的精度进一步提高,以实现更大规模的应用。
关键词:指派问题柔性调度理想点法遗传算法蚁群算法1.问题重述1.1问题背景车间生产调度是制造系统的基础,生产调度的优化方法是先进制造技术的核心技术。
-最小重量机器设计问题
-最小重量机器设计问题课题负责人名(学号):- 同组成员名单(角色):-指导教师:-评阅成绩:评阅意见:提交报告时间:xx年6 月17 日最小重量机器设计问题计算机科学与技术专业学生指导老师-[题目描述] 设某一机器由 n 个部件组成,每一种部件都可以从 m 个不同的供应商处购得。
高wij 是从供应商 j 处购得的部件 i 的重量,cij 是相应的价格。
试设计一个算法,给出总价格不超过 c 的最小重量机器设计。
编程任务:对于给定的机器部件重量和机器部件价格,编程计算总价格不超过 d 的最小重量机器设计。
数据输入:由文件 input、txt 给出输入数据。
第一行有3 个正整数 n,m 和 d。
接正业的2n 行,每行 n 个数。
前 n 行是 c,后 n 行是 w。
结果输出:将计算出的最小重量,以及每个部件的供应商输出到文件output、txt。
输入文件示例输出文件示例input、txt output、txt3344123131321222123321222[算法分析]采用回溯算法和分支定界法分别实现,对于回溯法,采用深度优先搜索对子集树进行剪枝,剪枝条件是当前的总费用不超过总费用;对于分支定界法,采用按照层次遍历对子集树进行剪枝,并将每层的结点按照重量由小到大进行排序,将相应下标保存在二维数组s中,以便构造最优解。
两种算法是时间复杂度都是O(m^n),空间复杂度均为O(nm),但由于分支定界法在已经排好序的序列中查找,因此查找到的第一个解即为最优解,理论上来说,时间效率会比回溯法高。
[程序实现]回溯法代码#include <iostream>#include<stdlib、h>#include <fstream>#include <vector>#include<stdio、h>#include <string、h>using namespace std;#define INF999999999#define MAXSIZE100+1intcur_solution[MAXSIZE];int solution[MAXSIZE];intw[MAXSIZE][MAXSIZE]; //weightint c[MAXSIZE][MAXSIZE];//costint minWeight; int cur_minWeight;void Backtrack(int t,int n,int m,int d){if(t>n){if(cur_minWeight < minWeight){//保存最优解和最优值minWeight =cur_minWeight;for(int r=1;r<=n;++r){solution[r] =cur_solution[r];}}}else{for(int i=1;i<=m;++i){d=w[t][i];//if(Constraint(t)&& Bound(t))Backtrack(t+1,n,m,d);d += c[t][i];}}return;}intmain(){int n,m,d;cout<<"Please input the input file path:"<<endl;charstrPath[63];while(scanf("%s",strPath)==1){ifstreamfin(strPath);cout<<"Please input the output filepath:"<<endl;cin>>strPath;ofstream fout(strPath);if(fin、good()&& fout、good()){minWeight = INF;cur_minWeight =0;fin>>n>>m>>d;intj,k;for(j=1;j<=n;++j){for(k=1;k<=m;++k){fin>>c[j][k];}}fo r(j=1;j<=n;++j){for(k=1;k<=m;++k){fin>>w[j][k];}}Backtrac k(1,n,m,d);fout<<minWeight<<endl;for(intr=1;r<=n;++r){fout<<solution[r]<<" ";}fout<<endl;fout、close();fin、close();}else{cout<<"Open fileerror!"<<endl;exit(0);}cout<<endl<<endl<<"Please input the input file path:"<<endl;}return 0;}分支定界法代码#include <stdio、h>#include <stdlib、h>#include<list>#include <iostream>using namespace std;#defineMAX_NODE256typedef struct _node{int weight,price;int level,th;struct _node *prev;}node;void qs(int *a,int*s,int b,int e)//快速排序{ int t,c=a[s[b]]; int l=b,r=e; while(l<r){ while(l<r&&a[s[r]]>=c)--r; t=s[r];s[r]=s[l];s[l]=t; while(l<r&&a[s[l]]<c)++l; t=s[r];s[r]=s[l];s[l]=t; }if(b<l)qs(a,s,b,l-1); if(l<e)qs(a,s,l+1,e);}intmain(){int *w=0,*p=0,n,m,c,i,j;int *minprice;intlevel,price,weight;list<node*> que;list<node*>::iteratorit;node *pnode;/* 读取文件 */FILE*pf;if((pf=fopen("input、txt","r"))!=0){fscanf(pf,"%d%d%d",&n,&m,&c);w=(int*)malloc(n*m*sizeof(int));//重量p=(int*)malloc(n*m*sizeof(int));//价格for(i=0;i<n;++i)for(j=0;j<m;++j)fscanf(pf,"%d",w+i*m+j);f or(i=0;i<n;++i)for(j=0;j<m;++j)fscanf(pf,"%d",p+i*m+j);fc lose(pf);}else{printf("no inputfile!!\n");getchar();exit(0);}/* 准备数据 */ints[n][m];//用来为每一种零件的质量排序,for(i=0;i<n;++i)for(j=0;j<m;++j)s[i][j]=j;minprice=(int*) malloc((n+1)*sizeof(int));//用来记录买了i个零件后,买完剩下的零件至少还要多少钱minprice[n]=0;//买了n个零件之后,不需要再买了for(i=0;i<n;++i){minprice[i]=p[i*m];for(j=1;j<m;++j)//找出买第i个零件的最低价格{minprice[i]=minprice[i]<p[i*m+j]?minprice[i]:p[i*m+j];}} for(i=n-2;i>=0;--i)//计算买剩下的零件至少要多少钱{minprice[i]=minprice[i+1]+minprice[i];}for(i=0;i<n;++i)/ /每种零件按重量排序,排序下标记录的s中,排序后w[i*m+s[i][j]],i相同时,对于变量j是递增的qs(w+i*m,s[i],0,m-1);/* 开始计算 */for(i=0;i<m;++i)//初始数据把第一种零件的所有情况放入活结点队列{pnode=new node;pnode->weight=w[s[0][i]];pnode->price=p[s[0][i]];if(pnode->price+minprice[2]<=c){pnode->th=i;pnode->level=1;pnode->prev =0;que、push_back(pnode);}else delete pnode;}while(!que、empty())//计算,直到得出结果或者队列为空{level =que、front()->level;price =que、front()->price;weight=que、front()->weight;if(level<n)for(i=0;i<m;++i)//如果队首不为叶子结点,扩展队首结点{pnode=new node;pnode->weight=weight+w[level*m+s[level][i]];pnode->price=price+p[level*m+s[level][i]];if(pnode->price+minprice[level+1]<=c)//剪枝,如果当前结点剩下的钱不够买全所有零件,则剪掉{pnode->th=s[level][i];pnode->level=level+1;pnode->prev =que、front();for(it=que、begin();it!=que、end();++it)//按重量递增构造优先队列if(pnode->weight<(*it)->weight)break;que、insert(it,pnode);if(level==n-1)break;//如果已经找到答案,退出循环}else delete pnode;}que、pop_front();if(i<m)break;//如果已经找到答案,退出循环}/* 输出答案 */if(pnode->level!=n){printf("can not find answer!!");getchar();exit(0);}pf=fopen("output、txt","w");if(pf){fprintf(pf,"%d\n",pnode->weight);int count=n,ans[n];while(pnode){ans[--count]=pnode->th;pnode=pnode->prev;}for(i=0;i<n;++i)fprintf(pf,"%d ",ans[i]);fputc('\n',pf);fclose(pf);}if(minprice)free(min price);if(w)free(w);if(p)free(p);return 0;}[运行结果]回溯法运行结果如下,分支定界法结果与下列一致,读者可以自行运行比对参考文献[1] 王晓东、计算机算法设计与分析、--3版、--北京:电子工业出版社xx、5。
最小重量机器设计问题最小重量机器设计问题
最小重量机器设计问题1.问题描述<1>.问题设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。
设Wij 是从供应商j处购得的部件i的重量,Cij 是相应的价格。
试设计一个算法,给出总价格不超过c的最小重量机器设计。
算法设计:对于给定的机器部件重量和机器部件价格,计算总价格不超过d的最小重量机器设计。
<2>.数据输入:由文件input.txt给出输入数据。
第一行有 3 个正整数 n ,m和 d。
接下来的2n 行,每行m个数。
前n行是c,后n行是w。
<3>.结果输出:将计算出的最小重量,以及每个部件的供应商输出output.txt Input.txt output.txt3 34 41 2 3 1 3 13 2 12 2 21 2 33 2 12 2 2<4>.算法设计:回溯算法中的递归回溯我采用的是子集树表示其解空间树。
cc表示当前所购买的机器总费用,在第i+1层的结点Z处,用cc记当前费用,若不满足cc<=cm,则以结点Z为根的子树中所有结点都不满足约束条件,因而该子树的解均为不可行解,可剪掉该子树。
MinSupply函数返回满足要求的最小机器重量。
Backtrack(i)搜索第i层子树,j=1,2,…m表示由1,2,…m供应商提供,bestx记录当前最优解。
当i<=n 时,当前扩展结点Z是子集树中的内部结点。
该结点有x[i]=1,2,3…m共m个子树,仅当cc+c[i][j]<=cm时进入x[i]=j的子树。
构成的解空间树如下:部件1:部件2:部件3:2.程序代码Supply.hclass Supply{public:friend int MinSupply(int **W,int **C,int m,int n,int d,int bestx[]); private:void Backtrack(int i);int n,//n个部件m,//m个供应商*x,//当前解*bestx,//当前最优解**w,//不同提供商提供不同部件的重量**c,//不同提供商提供不同部件的重量cw,//当前已选部件的总重量bestw,//当前最小载重量cm,//价格上限cc;//当前价格};Supply.cpp#include"Supply.h"void Supply::Backtrack(int i) {int j;//搜索第i层结点if(i>n){//到达叶结点if(bestw==0)bestw=cw;elseif(cw<bestw){for(i=1;i<=n;i++)bestx[i]=x[i];bestw=cw;}return;}//搜索子树for(j=1;j<=m;j++){if(cc+c[i][j]<=cm){x[i]=j;cw+=w[i][j];Backtrack(i+1);//搜索下一层结点cw-=w[i][j];//返回上一层结点时的操作}}}int MinSupply(int **W,int **C,int m,int n,int d,int bestx[]) {//返回最优载重量Supply X;//初始化XX.x=new int [n+1];//存n个部件分别取自的供应商X.w=W;X.c=C;X.n=n;X.m=m;X.cm=d;X.bestx=bestx;X.bestw=0;X.cw=0;X.Backtrack(1);delete []X.x;return X.bestw;}Main.cpp#include<iostream.h>#include<fstream.h>#include"Supply.h"void main(){ifstream in("input.txt");//定义读取文件if(in.fail()){cout<<"error file!"<<endl;return;}int weight[10][10],cost[10][10],n,m,d,bestx[10],i,j,Minw;int*p[10]={weight[0],weight[1],weight[2],weight[3],weight[4], weight[5],weight[6],weight[7],weight[8],weight[9]};int*q[10]={cost[0],cost[1],cost[2],cost[3],cost[4],cost[5],cost[6],cost[7],cost[8],cost[9]};in>>n>>m>>d;for(i=1;i<=n;i++)for(j=1;j<=m;j++)in>>cost[i][j];for(i=1;i<=n;i++)for(j=1;j<=m;j++)in>>weight[i][j];for(i=1;i<=n;i++)bestx[i]=0;Minw=MinSupply(p,q,m,n,d,bestx);ofstream out("output.txt");//定义输出文件out<<Minw<<'\n';cout<<Minw<<'\n';for(i=1;i<=n;i++){cout<<bestx[i]<<' ';out<<bestx[i]<<' '; }cout<<endl;}。
最小重量机器设计问题
最⼩重量机器设计问题问题描述:设某⼀机器由n个部件组成,每⼀种部件都可以从m个不同的供应商处购得。
设wij是从供应商j处够来的部件i的重量,cij是相应的价格。
试设计⼀个算法,给出总价格不超过c的最⼩重量机器设计。
算法设计:对于给定的机器部件重量和机器部件价格,计算总价值不超过d的最⼩重量机器设计。
数据输⼊:第⼀⾏由3个正整数n,m,d。
接下来的2n⾏,每⾏m个数。
前n⾏是c,后n⾏是w。
结果输出:将计算的最⼩重量及每个部件的供应商输出。
输⼊:3 3 41 2 33 2 12 2 21 2 33 2 12 2 2输出:41 3 12、解题思路:由于题⽬已经给出总价格的上限,因此算法通过使⽤回溯来选择合适的机器使得在总价格不超过d时得到的机器重量最⼩。
⾸先初始化当前价格cp=0,当前重量cw=0,此外,还要设置⼀个变量bestw表⽰选择机器的总重量,初始化其为每个部件从1号供应商购买的重量。
在循环选择i号机器时,判断从j号供应商购买机器后的价格是否⼤于总价格,如果不⼤于则选择,否则不选,继续选择下⼀供应商进⾏判断。
在得到⼀个合适的供应商后,继续选择下⼀机器的供应商,从第⼀个选到最后⼀个供应商。
当所有机器选择结束后,判断得到的总重量是否⽐之前的bestw⼩,如果⼩就赋给bestw,然后从这⼀步开始,回溯到上⼀机器,选择下⼀合适供应商,继续搜索可⾏解,直到将整个排列树搜索完毕。
这样,最终得到的bestw即为最优解。
当然,考虑到算法的时间复杂度,还可以加上⼀个剪枝条件,即在每次选择某⼀机器时,再判断选择后的当前重量是否已经⼤于之前的bestw,如果⼤于就没必要继续搜索了,因为得到的肯定不是最优解。
3、算法设计:a.部件有n个,供应商有m个,分别⽤array2[i][j]和array1[i][j]存储从供应商j 处购得的部件i的重量和相应价格,d为总价格的上限。
b.⽤递归函数machine(i)来实现回溯法搜索排列树(形式参数i表⽰递归深度)。
实验报告 最小重量机器设计问题
输入数据的第1行有3个正整数n,m和d(n,m<20,d<100)。接下来的2n行,每行n个数。前n行是c,后n行是w。
输出
将计算出的最小重量,以及每个部件的供应商分成两行输出。无解请输出“No Solution!”。
示例输入
3 3 4
1 2 3
3 2 1
2 2 2
1 2 3
3 2 1
2 2 2
const int len=30;
const int maxWeight=4000;
int n,m,cost;
int w[len][len];//重量
int c[len][len];//价钱
int visit[len];
int path[len];
int minWeight = maxWeight;
}
cout<<endl;
}
}
return 0;
}
结果:
二、实验总结与评价
实验总结(包括实验数据分析、实验结果、实验过程中出现的问题及解决方法等):
对实验的自我评价:
指导教师评语:
学生实验成绩评定:
指导教师签名:日期:年月日
对于给定的机器部件熏呈和机器部件价格设计一个优先队列式分支限界法计算总价格不的最小重贷机器设计
实验报告
课程名称:算法设计与分析
实验项目:最小重量机器设计问题
实验类型:综合性□设计性□验证性
专业班别:
姓名:
学号:
实验课室:第计算机实验室
指导教师:
实验日期:2013-12-12
一、实验项目训练方案
小组合作:是□否
1.练习使用回溯法求解“最小重量机器设计”问题。
算法设计课程报告最小重量机器设计问题
《算法设计》课程报告课题名称:算法设计课题负责人名(学号): ---同组成员名单(角色): ---指导教师: ---评阅成绩:评阅意见:提交报告时间:2014年 6 月 17 日最小重量机器设计问题计算机科学与技术专业学生 -- 指导老师 ---[题目描述] 设某一机器由 n 个部件组成,每一种部件都可以从m 个不同的供应商处购得。
高 wij 是从供应商 j 处购得的部件 i 的重量,cij 是相应的价格。
试设计一个算法,给出总价格不超过 c 的最小重量机器设计。
编程任务:对于给定的机器部件重量和机器部件价格,编程计算总价格不超过 d 的最小重量机器设计。
数据输入:由文件 input.txt 给出输入数据。
第一行有 3 个正整数 n,m 和 d。
接正业的 2n 行,每行 n 个数。
前 n 行是 c,后 n 行是 w。
结果输出:将计算出的最小重量,以及每个部件的供应商输出到文件output.txt。
输入文件示例输出文件示例input.txt output.txt3 34 41 2 3 1 3 13 2 12 2 2 1 23 3 2 1 2 2 2[算法分析]采用回溯算法和分支定界法分别实现,对于回溯法,采用深度优先搜索对子集树进行剪枝,剪枝条件是当前的总费用不超过总费用;对于分支定界法,采用按照层次遍历对子集树进行剪枝,并将每层的结点按照重量由小到大进行排序,将相应下标保存在二维数组s中,以便构造最优解。
两种算法是时间复杂度都是O(m^n) ,空间复杂度均为O(nm),但由于分支定界法在已经排好序的序列中查找,因此查找到的第一个解即为最优解,理论上来说,时间效率会比回溯法高。
[程序实现]回溯法代码#include <iostream>#include <stdlib.h>#include <fstream>#include <vector>#include <stdio.h>#include <string.h>using namespace std;#define INF 999999999#define MAXSIZE 100+1int cur_solution[MAXSIZE];int solution[MAXSIZE];int w[MAXSIZE][MAXSIZE]; //weightint c[MAXSIZE][MAXSIZE]; //costint minWeight;int cur_minWeight;void Backtrack(int t,int n,int m,int d){if(t>n){if(cur_minWeight < minWeight){//保存最优解和最优值minWeight = cur_minWeight;for(int r=1;r<=n;++r){solution[r] = cur_solution[r];}}}else{for(int i=1;i<=m;++i){d -= c[t][i];cur_solution[t] = i;cur_minWeight += w[t][i];if(d>=0) {Backtrack(t+1,n,m,d);}cur_minWeight -= w[t][i];//if(Constraint(t) && Bound(t)) Backtrack(t+1,n,m,d);d += c[t][i];}}return;}int main(){int n,m,d;cout<<"Please input the input file path:"<<endl;char strPath[63];while(scanf("%s",strPath)==1){ifstream fin(strPath);cout<<"Please input the output file path:"<<endl;cin>>strPath;ofstream fout(strPath);if(fin.good() && fout.good()){minWeight = INF;cur_minWeight = 0;fin>>n>>m>>d;int j,k;for(j=1;j<=n;++j){for(k=1;k<=m;++k){fin>>c[j][k];}}for(j=1;j<=n;++j){for(k=1;k<=m;++k){fin>>w[j][k];}}Backtrack(1,n,m,d);fout<<minWeight<<endl;for(int r=1;r<=n;++r){fout<<solution[r]<<" ";}fout<<endl;fout.close();fin.close();}else{cout<<"Open file error!"<<endl;exit(0);}cout<<endl<<endl<<"Please input the input file path:"<<endl;}return 0;}分支定界法代码#include <stdio.h>#include <stdlib.h>#include <list>#include <iostream>using namespace std;#define MAX_NODE 256typedef struct _node{int weight,price;int level,th;struct _node *prev;}node;void qs(int *a,int *s,int b,int e)//快速排序{int t,c=a[s[b]];int l=b,r=e;while(l<r){while(l<r&&a[s[r]]>=c)--r; t=s[r];s[r]=s[l];s[l]=t;while(l<r&&a[s[l]]<c)++l; t=s[r];s[r]=s[l];s[l]=t;}if(b<l)qs(a,s,b,l-1);if(l<e)qs(a,s,l+1,e);}int main(){int *w=0,*p=0,n,m,c,i,j;int *minprice;int level,price,weight;list<node*> que;list<node*>::iterator it;node *pnode;/* 读取文件 */FILE *pf;if((pf=fopen("input.txt","r"))!=0){fscanf(pf,"%d%d%d",&n,&m,&c);w=(int *)malloc(n*m*sizeof(int));//重量p=(int *)malloc(n*m*sizeof(int));//价格for(i=0;i<n;++i)for(j=0;j<m;++j)fscanf(pf,"%d",w+i*m+j);for(i=0;i<n;++i)for(j=0;j<m;++j)fscanf(pf,"%d",p+i*m+j);fclose(pf);}else{printf("no input file!!\n");getchar();exit(0);}/* 准备数据 */int s[n][m]; //用来为每一种零件的质量排序,for(i=0;i<n;++i)for(j=0;j<m;++j)s[i][j]=j;minprice=(int*)malloc((n+1)*sizeof(int));//用来记录买了i个零件后,买完剩下的零件至少还要多少钱minprice[n]=0; //买了n个零件之后,不需要再买了for(i=0;i<n;++i){minprice[i]=p[i*m];for(j=1;j<m;++j) //找出买第i个零件的最低价格{minprice[i]=minprice[i]<p[i*m+j]?minprice[i]:p[i* m+j];}}for(i=n-2;i>=0;--i) //计算买剩下的零件至少要多少钱{minprice[i]=minprice[i+1]+minprice[i];}for(i=0;i<n;++i) //每种零件按重量排序,排序下标记录的s中,排序后w[i*m+s[i][j]],i相同时,对于变量j是递增的qs(w+i*m,s[i],0,m-1);/* 开始计算 */for(i=0;i<m;++i) //初始数据把第一种零件的所有情况放入活结点队列{pnode=new node;pnode->weight=w[s[0][i]];pnode->price=p[s[0][i]];if(pnode->price+minprice[2]<=c){pnode->th=i;pnode->level=1;pnode->prev =0;que.push_back(pnode);}else delete pnode;}while(!que.empty()) //计算,直到得出结果或者队列为空{level =que.front()->level;price =que.front()->price;weight=que.front()->weight;if(level<n)for(i=0;i<m;++i) //如果队首不为叶子结点,扩展队首结点{pnode=new node;pnode->weight=weight+w[level*m+s[level][i]];pnode->price=price+p[level*m+s[level][i]];if(pnode->price+minprice[level+1]<=c) //剪枝,如果当前结点剩下的钱不够买全所有零件,则剪掉{pnode->th=s[level][i];pnode->level=level+1;pnode->prev =que.front();for(it=que.begin();it!=que.end();++it) //按重量递增构造优先队列if(pnode->weight<(*it)->weight)break;que.insert(it,pnode);if(level==n-1)break; //如果已经找到答案,退出循环}else delete pnode;}que.pop_front();if(i<m)break; //如果已经找到答案,退出循环}/* 输出答案 */if(pnode->level!=n){printf("can not find answer!!");getchar();exit(0);}pf=fopen("output.txt","w");if(pf){fprintf(pf,"%d\n",pnode->weight);int count=n,ans[n];while(pnode){ans[--count]=pnode->th;pnode=pnode->prev;}for(i=0;i<n;++i)fprintf(pf,"%d ",ans[i]);fputc('\n',pf);fclose(pf);}if(minprice)free(minprice);if(w)free(w);if(p)free(p);return 0;}[运行结果]回溯法运行结果如下,分支定界法结果与下列一致,读者可以自行运行比对参考文献[1] 王晓东.计算机算法设计与分析.--3版.--北京:电子工业出版社2007.5。
基于回溯法的最小重量机器设计问题算法设计
基于回溯法的最小重量机器设计问题算法设计1.问题描述设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。
设wij是从供应商j处购得的部件i的重量,cij是相应的价格。
试设计一个算法,给出总价格不超过c的最小重量机器设计。
2.方法简介回溯法是一个既带有系统性又带有跳跃性的搜索算法,可以系统的搜索问题的所有解。
回溯法在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树。
算法搜素至解空间的任一结点时,先判断该结点是否包含问题的解。
如果肯定不包含,则跳过对以该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜素。
回溯法求问题的所有解时,要回溯到根,且根节点的所有子树都被搜索遍才结束。
回溯法求问题的一个解时,只要搜索到问题的一个解就可结束。
2.1回溯法的思想用回溯法解问题时,要明确定义问题的解空间和组织结构。
问题的解空间应至少包含问题的一个(最优)解。
通常回溯法的组织结构为树或图。
2.1.1用回溯法解决问题的步骤:1.定义问题的解空间。
例如:对于有n种可选择物品的0-1背包问题,其解空间由长度为n的0-1向量组成。
该解空间包含对变量的所有0-1赋值。
当n=3时,其解空间是:{(0,0,0,),(0,0,1),(0,1,0),(0,1,1,),(1,0,0),(1,0,1),(1,1,0),(1,1,1,)}2.组织解空间。
将解空间组织成树或图或其他形式,使得能用回溯法很好的搜索整个解空间。
3.以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
2.1.2解空间的搜索方法:1.从开始结点(根结点)出发,将开始结点作为活结点,同时作为当前的扩展节点。
2.在当前扩展结点处,搜索向纵深方向移至一个新结点。
3.新结点成为新的活结点,并成为当前扩展结点。
4.若在当前扩展结点处不能再向纵深方向移动,当前扩展节点成为死结点。
5.从该死结点往回移至最近的活结点处,将这个活结点作为当前的扩展结点。
最小重量机器设计实验报告
最小重量机器设计实验报告1. 引言最小重量机器设计是一个重要的工程问题,它的目标是在给定的约束条件下,找到一个重量最小的机器设计方案。
这个问题在很多领域都有应用,比如航空航天、汽车制造等。
本实验旨在通过设计一个最小重量的机械结构,来探讨最小重量机器设计的方法和原理。
2. 实验目的本实验的主要目的是通过设计一个最小重量机械结构,来研究最小重量机器设计的基本原理和实现方法。
具体目标如下:1. 了解最小重量机器设计的概念和意义;2. 掌握用于最小重量机器设计的优化方法;3. 设计一个最小重量机械结构,并进行实验验证。
3. 实验原理最小重量机器设计可以归纳为一个优化问题,即在给定的约束条件下,求解一个目标函数的最小值。
在机械设计中,重量往往是一项重要的指标,因为过重的机器具有较高的材料成本和能源消耗。
常用的最小重量机器设计方法包括:- 材料优化:通过选择合适的材料和结构形式,来降低机器的重量;- 结构优化:通过优化机器的结构形式,来减少无效载荷和材料浪费;- 拓扑优化:通过调整机器的拓扑结构,来达到最小重量的设计。
4. 实验步骤本实验选择了一种简化的机械结构,以便于说明最小重量机器设计的方法和原理。
具体步骤如下:1. 设计机器的初始结构,包括主体部分和连接部件;2. 运用材料优化方法,选择合适的材料,并计算机器的初始重量;3. 运用结构优化方法,对机器的结构进行调整,以减少无效载荷和材料浪费;4. 运用拓扑优化方法,对机器的拓扑结构进行调整,以达到最小重量的设计;5. 制作并测试实验样品,记录实际重量和性能数据;6. 进行数据分析和结论总结。
5. 实验结果与讨论经过优化设计和实验测试,我们得到了最小重量机械结构的设计方案,并进行了性能测试。
实验结果表明,该设计方案在满足约束条件的前提下,成功实现了最小重量机器设计的目标。
这为机械工程领域的设备设计和产品改进提供了重要参考。
6. 结论本实验通过设计一个最小重量的机械结构,探讨了最小重量机器设计的方法和原理。
分支限界法解决最小重量机器问题
#include <stdio.h>#include <stdlib.h>int bottom,Flag2;int COST,n,m,*bestx;int cc,cw,w[100][100];int cp,c[100][100];int bestw=1000;int Flag;int E;int bext[100];int bestxulie[100],sum;struct Heapnode{int profit;int weight;int level;int prt;int current;};struct Heapnode H[100];struct Heapnode N;int MinWeightMachine(){int i=1,j,wt=0,ct=0;cw=0;cp=0;int besTypep=0;while(1){for(j=1; j<=m; j++){wt=cw+w[i][j];ct=cp+c[i][j];if(ct<=COST&&i<=n){if(i==n){int k;if(wt<bestw){bestw=wt;for(k=1; k<n-1; k++)bestxulie[k]=bext[k+2];bestxulie[n]=j;for(k=1; k<n-1; k++)sum+=w[k][bestxulie[k]];sum+=w[n][j];for(k=1; k<=n; k++){if(w[n-1][k]==(bestw-sum))bestxulie[n-1]=k;}}}elseAddLiveNode(ct,wt,i+1,j);}}if(bottom==Flag)break;DeleteMin(N);cw=N.weight;cp=N.profit;i=N.level;Flag2=N.current;bext[i]=N.prt;}return bestw;}void AddLiveNode(int cp,int cw,int i,int j){N.profit=cp;N.weight=cw;N.level=i;N.current=j;N.prt=Flag2;Insert(N);}void DeleteMin(){N.level=H[bottom].level;N.profit=H[bottom].profit;N.prt=H[bottom].prt;N.current=H[bottom].current;N.weight=H[bottom].weight;bottom++;}void Insert(){H[Flag].level=N.level;H[Flag].profit=N.profit;H[Flag].prt=N.prt;H[Flag].current=N.current;H[Flag].weight=N.weight;Flag++;}int main(){int i,j;scanf("%d%d%d",&n,&m,&COST);for(i=1; i<=n; i++)for(j=1; j<=m; j++)scanf("%d",&c[i][j]);for(i=1; i<=n; i++)for(j=1; j<=m; j++)scanf("%d",&w[i][j]);printf("最小重量为:\n");printf("%d\n",MinWeightMachine());printf("每个物品对应的供应商为:\n");for(i=1; i<=n; i++)printf("%d ",bestxulie[i]);return 0;}。
软件工程课程实习题目
软件工程课程实习题目1、设有n个运动员要进行网球循环赛。
设计一个满足以下要求的比赛日程表:(1)每个选手必须与其他n-1个选手各赛一次。
(2)每个选手一天只能赛一次。
(3)当n是偶数时,循环赛进行n-1天。
当n是奇数时,循环赛进行n天。
2、考虑国际象棋棋盘上某个位置的一只马,它是否可能只走63步,正好走过除起点外的其他63个位置各一次?如果有一种这样的走法,则称所走的这条路线为一条马的周游路线。
试设计一个程序输出这样的一条马的周游路线。
3、Gray码是一个长度为2n的序列。
序列中无相同元素,每个元素都是长度为n位的串,相邻元素恰好只有一位不同。
设计一个程序实现对任意的n构造相应的Gray码。
4、多边形游戏问题是1998年国际信息学奥林匹克竞赛试题。
该游戏是一个单人玩的游戏,开始时有一个由n个顶点构成的多边形。
每个顶点被赋予一个整数值,每条边被赋予一个运算符“+”或“*”。
所有边依次用整数从1到n编号。
游戏的地一步,将一条边删除。
随后n-1步按以下方式操作:(1)选择一条边E以及由E连接着的两个顶点V1和V2;(2)用一个新的顶点取代边E以及由E连接着的两个顶点V1和V2。
将由顶点V1和V2的整数值通过边E上的运算得到的结果赋予新的顶点;(3)最后,所有边都被删除,游戏结束。
游戏的得分就是所剩顶点上的整数值。
5、在一个圆形操场的四周摆放着n堆石子。
现要将石子有次序地合并成一堆。
规定每次只能选相邻的两堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。
试设计一个程序,计算出将n堆石子合并成一堆的最小得分和最大得分。
6、商店中每种商品都有标价。
例如:一朵花的价格是2元,一个花瓶的价格是5元。
为了吸引顾客,商店提供了一组优惠商品。
优惠商品是把一种或多种商品分成一组,并降价销售。
例如:3朵花的价格不是6元而是5元。
2个花瓶加1朵花的优惠价格是10元。
试设计一个程序,计算出某个顾客所购商品应付的最少费用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、算法实现题5-3 最小重量机器设计问题
设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。
设w[i][j]是从供应商j处购得的部件i的重量,c[i][j]是相应的价格,给出总价格不超过d的最小重量机器设计。
1、解题说明
这是一个最优规划问题,采用本章回溯法来求解。
解空间是一个子集树,因此通过递归函数对解空间进行深度优先搜索,只要在当前结点,只要满足限定条件和限界条件,则递归下一层,否则就尝试下一个供应商。
Backtrack(1)实现对整个解空间的回溯搜索,Backtrack(i)搜索解空间中第i层子树。
类Machine的数据成员记录界空间中结点信息。
在算法Backtrack中,当i>n的时候,算法搜索至叶节点,得到一个新的可行解,与当前最优解进行比较,并更新最优值。
当i<=n的时候,当前扩展结点是解空间中的内部结点。
该结点有m个子节点。
若满足当前总费用小于最大总费用,并且当前总重量小于最小总重量,那么以深度优先的方式递归地对可行子树进行搜索,或剪去不可行子树。
2、程序代码
#include<iostream>
#include<fstream>
using namespace std;
class Machine{ //机器类
public:
Machine(){ //构造函数
cw=cc=0;
minw=1000;
ifstream in("input.txt"); //从文件输入
in>>n>>m>>d;
bestprovider=new int[m+1]; //初始化最优供应商和供应商数组
provider=new int[m+1];
c=new double*[n+1]; //创建部件价格二维数组
for(i=1;i<=n;i++)
c[i]=new double[m+1];
for(i=1;i<=n;i++) //从文件读入价格
for(int j=1;j<=m;j++)
in>>c[i][j];
w=new double*[n+1]; //创建部件重量二维数组
for(i=1;i<=n;i++)
w[i]=new double[m+1];
for(i=1;i<=n;i++) //从文件读入重量
for(int j=1;j<=m;j++)
in>>w[i][j];
}
void Backtrack(int i){
if(i>n){ //已得到一个可行解
if(cw<minw){ //更新最小重量
minw=cw;
for(int j=1;j<=m;j++)
bestprovider[j]=provider[j];
}
return;
}
for(int j=1;j<=m;j++)
{
provider[i]=j;
//考虑第j个供应商
cc+=c[i][j];
cw+=w[i][j];
//满足限定条件并且满足限界条件,则递归下一层if(cc<=d&&cw<minw)
Backtrack(i+1);
//考虑下一个供应商
cc-=c[i][j];
cw-=w[i][j];
}
}
void Output(){ //输出到文件
ofstream out("output.txt");
cout<<minw<<endl;
out<<minw<<endl;
for(int k=1;k<=m;k++){
out<<bestprovider[k]<<' ';
cout<<bestprovider[k]<<' ';
}
out<<endl;
cout<<endl;
}
private:
int n,m,d,i; //n为部件个数,m为供应商个数,d为总价格上届,i为层数
double **w; //部件重量数组
double **c; //部件价格数组
double cw,cc,minw; //cw为当前重量,cc为当前价格,minw为最小重量
int *provider; //供应商数组
int *bestprovider; //最优供应商数组
};
int main(){
Machine mach;
mach.Backtrack(1);
mach.Output();
return 0;
}
3、运行截图
1)程序所在文件夹有input.txt,运行完成后产生了output.txt
2)输入文件input.txt
第一行分别是部件数量n,供应商数量m,和最大费用d;
紧接着输入一个n行m列的部件价格数组和一个n行m列的部件重量数组。
3)运行程序后,打开ouput.txt,输出结果如下:
Dos界面运行如下:
二、算法实现题5-13 工作分配问题
设有n件工作分配给n个人。
将工作i分配给第j个人所需的费用为cij 。
试设计一个算法,为每一个人都分配1 件不同的工作,并使总费用达到最小。
设计一个算法,对于给定的工作费用,计算最佳工作分配方案,使总费用达到最小。
1、解题说明
工作分配问题的解空间是一个排列树。
按照回溯法搜索排列数的算法框架。
相应的排列树由work[1:n]的所有排列给出。
在递归算法Backtrack中,当i>n的时候,算法搜索至叶节点,得到新的排列方案。
若当前总费用小于最小总费用,则更新最小总费用的值。
并返回。
当i<=n的时候,当前扩展结点位于排列树中,此时算法判断当前总费用是否小于最小总费用,若小于,则以深度优先的方式递归地对相应子树进行搜索。
否则剪去相应子树。
2、程序代码
#include<iostream>
#include<fstream>
using namespace std;
class Work{ //工作类
public:
Work(){ //构造函数
cc=0; //当前总费用赋初值为0
minc=10000; //最小费用赋初值为10000
ifstream in("input.txt"); //从文件读入n
in>>n;
work=new int[n+1]; //初始化工作数组
for(i=1;i<=n;i++)
{
work[i]=i;
}
c=new int*[n+1]; //创建费用二维数组
for(i=1;i<=n;i++)
c[i]=new int[n+1];
for(i=1;i<=n;i++){ //从文件读入二维数组for(int j=1;j<=n;j++)
{
in>>c[i][j];
cout<<c[i][j]<<" ";
}
cout<<endl;
}
}
void Backtrack(int i){
if(i>n){ //已得到一个可行解
if(cc<minc) //更新最小费用
minc=cc;
return;
}
for(int j=i;j<=n;j++)
{
if(cc<minc){ //搜索子树
swap(work[i],work[j]);
cc+=c[i][work[i]];
Backtrack(i+1);
cc-=c[i][work[i]];
swap(work[j],work[i]);
}
}
}
void Output(){
ofstream out("output.txt");
cout<<minc<<endl;
out<<minc<<endl;
}
public:
int n,i,j;
int **c;
int *work;
int cc,minc;
void swap(int &a,int &b){
int temp=a;
a=b;
b=temp;
}
};
int main(){
Work wk;
wk.Backtrack(1);
wk.Output();
return 0;
}
3、运行截图
1)程序所在文件夹有input.txt,运行完成后产生了output.txt
2)输入文件input.txt
第一行为工作数量n;接下来是n行n列的二维数组,表示每个工作分配给每个人的对应工作费用。
3)运行程序后,打开ouput.txt,输出结果如下:
dos界面运行如下:。