最小重量机器设计问题
概述
一、实验目的
1、了解回溯法和分支限界法的基本思想。
2、运用回溯法和分支限界法解决最小重量机器设计问题。
二、实验要求
最小重量机器设计问题:设某一机器由n个部件组成,每一种部件可以从m个不同的供应商处购得。设wij是从供应商j处购得的部件i的重量,cij是相应的价格。试设计一个算法,给出总价格不超过c的最小重量机器设计。分别用回溯法和分支限界法实现问题的算法。
三、算法思想和实现
1、回溯法
(1)此问题是一棵排列树,设开始时bestx=[-1,-1,……,-1]则相应的排列树由x[0:n-1]的所有排列构成。
(2)找最小重量机器设计的回溯算法Backtrack是类machine的公有成员。私有数据成员整型数组Savex保存搜索过的路径,到达叶节点后将数据赋值给数组bestx。成员bestw记录当前最小重量,cc表示当前花费,cw表示当前的重量。
(3)在递归函数Backtrack中,在保证总花费不超过c的情况下:
当i=n时,当前扩展结点是排列树的叶节点。此时搜索到一个解,判断此时的最小重量是否小于当前最小重量,若小于则更新bestw,并得到搜索路径bestx。
当i< P>
#include
using namespace std;
#define N 3
#define M 3
int w[N][M]={{1,2,3},{3,2,1},{2,2,2}};
int c[N][M]={{1,2,3},{3,2,1},{2,2,2}};
class machine
{public:
void InitMachine(int C);
void Backtrack(int i);
void printsave();
private:
int COST;//题目中的C
int cw;//当前的重量
int cc;//当前花费
int bestw;//当前最小重量
int bestx[N];//最优解
int savex[N];//savex[i]如果为j,表示第i个零件应该选用第j个人供应的
};
void machine::InitMachine(int C){
COST=C;
cw=cc;
bestw=-1;//初值为-1,标记最小重量是否变化
for(int j=0;j< P>
bestx[j]=-1;
}
void machine::Backtrack(int i)
{ if(i>=N)//达到叶子节点
{if(cw<以前最小重量><>
{
bestw=cw;
cout<<"************************************"<< P>
cout<<"搜索路径的bestw:"<<
for(int k=0;k<>
{
cout<<<"";< P>
savex[k]=bestx[k];
}
cout<< P>
}
return;
}
for(int j=0;j<>
{
if((cc+c[i][j]0))
{cc+=c[i][j];
cw+=w[i][j];
bestx[i]=j;
Backtrack(i+1);
bestx[i]=-1;
cc-c[i][j];
cw-=w[i][j];
}
}
void machine::printsave(){
if(bestw==-1) { cout<<"输入的总价格太小!"<< P>
}
else {
cout<<"************************"<< P>
cout<<"最优重量(bestw )是:"<<
for(int k=0;k< P>
cout<<"第"<<<"个部件由第"<<<"供应商供应"<< P>
cout<< P>
}
}
int main(){
mach Mach;
int C;
cout<<"输入总价格不超过的C:";
cin>>C;//输入最小花费
Mach.InitMachine(C);
Mach.Backtrack(0);
Mach.printsave();
return 0;
}
2、分支限界法
解空间为一棵排列树,采用优先队列式分支限界法找出所给的最小重量机器设计,开始时,将排列树的根节点置为当前扩展结点。在初始扩展结点处还设有选定部件是哪个供应商提供的,故cv=0,cw=0,position=0,peer=0,1≤i≤n。x[1:n]记录供应商的选择while完成对排列树内部结点的有序扩展。循环体内依次从活结点优先队列中取出具有最小重量的结点,依次为当前扩展结点。并且花费不超过c并加以扩展,队列为空时则结束循环。当peer=n时,此时扩展结点是叶节点,得到当前的最小重量和最优解数组x。若peer< P>
#include "fstream.h"
#include "iostream.h"
struct nodetype {
int peer;
struct nodetype *parent;
int position;
double cw;
double cv;
double r; };
struct nodetype *queues[100000000];
/小根堆///
void insert(struct nodetype *x, int oldlast) //x是要插入的数
{ //oldlast是目前堆的元素数目
int last = oldlast+1;
queues[last]=x;
int i=last;
while((i > 1)&&(queues[i]->r < queues[i/2]->r)) {
struct nodetype *temp;
temp=queues[i];
queues[i]=queues[i/2];
queues[i/2]=temp;
i = i/2;
}
} //last是当前堆的元素个数,执行该函数后
struct nodetype * deletemin(int last,struct nodetype *a[])
{ //返回堆的第一个元素(即最小元素)
struct nodetype *temp;
temp=a[1];
a[1]=a[last];
last --;
int i = 1;
int j=0;
while(i <= last/2)
{ if((a[2*i]->r < a[2*i+1]->r)||(2*i == last)) j = 2*i;
elsej=2*i+1; if(a[i]->r > a[j]->r) {
struct nodetype *temp;
temp=a[i];
a[i]=a[j];
a[j]=temp;
i = j;
}
else return(temp);
}
return(temp);
}
void main() /小根堆///
{
ifstream fin("input.txt");
ofstream fout("output.txt");
int n,m,c;
fin>>n;fin>>m;fin>>c;
double **w=new double*[n+1];
double **cc=new double*[n+1];
for(int i=1;i<=n;i++){
w[i]=new double[m+1];
cc[i]=new double[m+1];
}
for(i=1;i<=n;i++)
for(int j=1;j<=m;j++)
fin>>cc[i][j];
for(i=1;i<=n;i++)
for(int j=1;j<=m;j++)
fin>>w[i][j];
double *cmin=new double[n+1];
double *wmin=new double[n+1];
for(i=1;i<=n;i++) {
cmin[i]=cc[i][1];
wmin[i]=w[i][1];
for(int j=2;j<=m;j++) {
if(cmin[i]>cc[i][j]) cmin[i]=cc[i][j];
if(wmin[i]>w[i][j]) wmin[i]=w[i][j];
}
}
double *rc=new double[n+1];//剩余部件最小价格和
double *rw=new double[n+1];//剩余部件最小重量和
rc[n]=0;rw[n]=0;
for(i=n-1;i>=1;i--) {
rc[i]=rc[i+1]+cmin[i+1];
rw[i]=rw[i+1]+wmin[i+1];
}
struct nodetype *node=new struct nodetype;
node->peer=0;
node->cv=0;
node->cw=0;
node->position=0;
node->r=rw[1]+wmin[1];
insert(node,0);
int cpeer=0;
int q_len=1;
bool isend=false;
while(!isend&&q_len>0)
{ node=deletemin(q_len,queues);
q_len--;
if(node->peer==n) {
isend=true;
fout<cw<< *x="new" int>
for(int k=n;k>=1;k--) {
x[k]=node->position;
node=node->parent;
}
for(k=1;k<=n;k++) fout<<<" P < ?; >
return;}
}
四、结果
input.txt
3 3 4
1 2 3
3 2 1
2 2 2
1 2 3
3 2 1
2 2 2
output.txt
4
1 3 1
五、总结
分支限界法与回溯法对当前扩展结点所采用的扩展方式不同。在分支限界法中,每一个结点只有一次机会成为扩展结点。而在回溯法中,每一个活结点有多次机会成为扩展结点。
如果您喜欢这篇文章请点击右上角按钮, 即可分享到《朋友圈》或许 你小小的一个分享动作就可以照亮无数人的命运。
欢迎关注公众微信:yingchunhua365
扫描以下二维码
传递正能量,分享励志故事,
从这里起航……
请把正能量传递下去,
帮助和影响更多的人,
最后
以上就是聪慧茉莉为你收集整理的最小重量机器设计问题的全部内容,希望文章能够帮你解决最小重量机器设计问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
- 本文分类:数据结构
- 浏览次数:63 次浏览
- 发布日期:2023-12-24 06:35:09
- 本文链接:https://www.kaopuke.com/article/k-p-k_13_u_23_o_2_f4_13__7__2_4.html
发表评论 取消回复