#include<iostream>
#include<fstream>
using namespace std;typedef int Type;
#define N 5
#define ZERO_VALUE_OF_TYPE 0
#define MAX_VALUE_OF_TYPE 2147483647typedef struct node_data{Type c[N][N];       //费用矩阵int row_init[N];    //费用矩阵的当前行映射为原始行int col_init[N];    //费用矩阵的当前列映射为原始列int row_cur[N];     //费用矩阵的当前行映射为原始行int col_cur[N];     //费用矩阵的当前列映射为原始列int ad[N];          //回路顶点邻接表int k;              //当前费用矩阵的阶Type w;             //节点的下界struct node_data *next;    //队列链指针
}NODE;Type c[N][N];
Type ad[N];
/*
NODE *xnode;          //父亲结点指针
NODE *ynode;          //儿子结点指针
NODE *znode;          //儿子结点指针
NODE *qbase;          //优先队列首指针
Type bound;          //当前可行解的最优值
*///计算node所指向结点的费用矩阵行row最小值
Type row_min(NODE *node,int row,Type &second)
{Type temp;int i;int flag=0;if(node->c[row][0] < node->c[row][1]){temp=node->c[row][0];second=node->c[row][1];}else{temp=node->c[row][1];second=node->c[row][0];}for(i=2;i<node->k;i++){if(node->c[row][i]<temp){second=temp;temp=node->c[row][i];}else if(node->c[row][i]<second)second = node->c[row][i];}for(i=0;i<node->k;i++)   //如果整行都是最大值则不进行归约,列同if(node->c[row][i]==MAX_VALUE_OF_TYPE)flag++;if(node->k==flag)return 0;return temp;
}//计算node所指向结点的费用矩阵列col最小值
Type col_min(NODE *node,int col,Type &second)
{Type temp;int i;int flag=0;if(node->c[0][col] < node->c[1][col]){temp=node->c[0][col];second=node->c[1][col];}else{temp=node->c[1][col];second=node->c[0][col];}for(i=2;i<node->k;i++){if(node->c[i][col]<temp){second = temp;temp = node->c[i][col];;}else if(node->c[i][col]<second)second=node->c[i][col];}for(i=0;i<node->k;i++)if(node->c[i][col]==MAX_VALUE_OF_TYPE)flag++;if(node->k==flag)return 0;return temp;
}//归约node所指向结点的费用矩阵
Type array_red(NODE *node)
{int i,j;Type temp,temp1,sum=ZERO_VALUE_OF_TYPE;for(i=0;i<node->k;i++){         //行归约temp=row_min(node,i,temp1);  //行归约常数for(j=0;j<node->k;j++){if(node->c[i][j]==MAX_VALUE_OF_TYPE)  //跳过最大值continue;node->c[i][j]-=temp;}sum += temp;                   //行归约常数累计}for(j=0;j<node->k;j++){         //列归约temp=col_min(node,j,temp1);  //列归约常数for(i=0;i<node->k;i++){if(node->c[i][j]==MAX_VALUE_OF_TYPE)  //跳过最大值continue;node->c[i][j]-=temp;}sum+=temp;                   //列归约常数累计} return sum;                      //返回归约常数}//计算node所指向结点的费用矩阵Dkl,选择搜索分支的边
Type edge_sel(NODE *node,int &vk,int &vl)
{int i,j;Type temp,d=ZERO_VALUE_OF_TYPE;Type *row_value = new Type[node->k];Type *col_value = new Type[node->k];for(i=0;i<node->k;i++)                  //每一行的次小值row_min(node,i,row_value[i]);for(i=0;i<node->k;i++)                  //每一列的次小值col_min(node,i,col_value[i]);for(i=0;i<node->k;i++){     //对费用矩阵所有为0的元素计算相应的temp值for(j=0;j<node->k;j++){if(node->c[i][j]==ZERO_VALUE_OF_TYPE){temp=row_value[i]+col_value[j];if(temp>d){               //求最大的temp值dd=temp;vk=i;vl=j;                //保存相应的行列号}}}}delete row_value;delete col_value;return d;
}//删除node所指向结点的费用矩阵第vk行第vl列的所有元素
void del_rowcol(NODE *node,int vk,int vl)
{int i,j,vk1,vl1;for(i=vk;i<node->k-1;i++)      //元素上移for(j=0;j<vl;j++)node->c[i][j] = node->c[i+1][j];for(j=vl;j<node->k-1;j++)      //元素左移for(i=0;i<vk;i++)node->c[i][j] = node->c[i][j+1];for(i=vk;i<node->k-1;i++)      //元素上移及左移for(j=vl;j<node->k-1;j++) node->c[i][j] = node->c[i+1][j+1];vk1 = node->row_init[vk];   //当前行vk转换为原始行vk1node->row_cur[vk1] = -1;    //原始行删除标志for(i=vk1+1;i<N;i++)        //vk1之后的原始行,其对应的行号减一node->row_cur[i]--;vl1 = node->col_init[vl];   //当前列vl转换为原始列vl1node->col_cur[vl1]=-1;      //原始列删除标志for(i=vl1+1;i<N;i++)        //vl1之后的原始列,其对应的列号减一node->col_cur[i]--;for(i=vk;i<node->k-1;i++){  //修改vk及其之后的当前行的对应原始行号node->row_init[i] = node->row_init[i+1];}for(i=vl;i<node->k-1;i++)   //修改vl及其之后的当前列的对应原始列号node->col_init[i] = node->col_init[i+1];node->k--;                  //当前矩阵的阶数减一
}//登记回路顶点邻接表,旁路有关的边
void edg_byp(NODE *node,int vk,int vl)
{int k,l;vk=node->row_init[vk];            //当前行号转换为原始行号vl=node->col_init[vl];             //当前列号转换为原始列号node->ad[vk]=vl;             //登记回路顶点邻接表k=node->row_cur[vl];        //vl转换为当前行号kl=node->col_cur[vk];        //vk转换为当前列号lif((k>0)&&(l>=0)){     //当行、列号均处于当前矩阵中旁路相应的边node->c[k][l] = MAX_VALUE_OF_TYPE;}
}//初始化
NODE *initial(Type c[][N],int n)
{int i,j;NODE *node=new NODE;       //分配结点缓冲区for(i=0;i<n;i++)           //复制费用矩阵的初始数据for(j=0;j<n;j++){node->c[i][j]=c[i][j];}for(i=0;i<n;i++){       //建立费用矩阵原始行、列号与初始行、列号的关系node->row_init[i]=i;node->col_init[i]=i;node->row_cur[i]=i;node->col_cur[i]=i;} for(i=0;i<n;i++){          //回路顶点邻接表初始化为空node->ad[i]=-1;}node->k=n; return node;            //返回结点指针
}void Q_insert(NODE *qbase,NODE *xnode){NODE *p;if(qbase->next==NULL){qbase->next=xnode;xnode->next=NULL;}else if(xnode->w < qbase->next->w){xnode->next=qbase->next;qbase->next=xnode;}else{p=qbase->next;while(p->next){if((xnode->w > p->w)&&(xnode->w < p->next->w)){xnode->next=p->next;p->next=xnode;break;}p=p->next;}if(p->next==NULL){p->next=xnode;xnode->next=NULL;}}p=qbase->next;}NODE *Q_delete(NODE *qbase){NODE *p;p=qbase->next;qbase->next=p->next;return p;
}//货郎担问题的分支限界算法
template <class Type>
Type traveling_salesman(Type c[][N],int n,int ad[])
{int i,j,vk,vl;Type d,w,bound=MAX_VALUE_OF_TYPE;NODE *xnode,*ynode,*znode,*qbase;qbase=new NODE;qbase->next=NULL;xnode=initial(c,n);        //初始化父亲结点        xnode->w = array_red(xnode);   //归约费用矩阵while(xnode->k!=0){          d=edge_sel(xnode,vk,vl);     //选择分支方向并计算Dklznode=new NODE;             //建立分支结点(右儿子结点)*znode = *xnode;              //x结点的数据复制到z结点znode->c[vk][vl]=MAX_VALUE_OF_TYPE;   //旁路Z结点的边      array_red(znode);            //归约z结点的费用矩阵       znode->w = xnode->w + d;       //计算z结点的下界if(znode->w<bound)             //若下界小于当前可行解最优值Q_insert(qbase,znode);     //z结点插入优先队列 else delete znode;             //否则剪去该结点        ynode=new NODE;             //建立分支结点(左儿子结点)*ynode=*xnode;              //x结点数据复制到y结点edg_byp(ynode,vk,vl);       //登记回路顶点的邻接表,旁路有关的边ynode->c[vl][vk]=MAX_VALUE_OF_TYPE;   del_rowcol(ynode,vk,vl);    //删除y结点费用矩阵当前vk行vl列ynode->w = array_red(ynode);  //归约y结点费用矩阵        ynode->w += xnode->w;        //计算y结点的下界if(ynode->k==2){             //费用矩阵只剩下2阶if((ynode->c[0][0] == ZERO_VALUE_OF_TYPE)&&(ynode->c[1][1] == ZERO_VALUE_OF_TYPE)){ynode->ad[ynode->row_init[0]] = ynode->col_init[0];ynode->ad[ynode->row_init[1]] = ynode->col_init[1];}else{ynode->ad[ynode->row_init[0]] = ynode->col_init[1];ynode->ad[ynode->row_init[1]] = ynode->col_init[0];}                         //登记最后两条边ynode->k=0;}if(ynode->w<bound){          //若下界小于当前可行解最优值Q_insert(qbase,ynode);   //y结点插入优先队列if(ynode->k==0)          //更新当前可行解最优值bound = ynode->w;}else delete ynode;    //否则剪去y结点xnode=Q_delete(qbase);   //取优先队列首元素} w=xnode->w;               //保存最短路线费用for(i=0;i<n;i++){         //保存路线的顶点邻接表ad[i]=xnode->ad[i];}delete xnode;              //释放x结点的缓冲区while(qbase->next){             //释放队列结点缓冲区xnode = Q_delete(qbase);delete xnode;} return w;            //回送最短路线费用
}void main(){int i,j;ifstream fin("1.txt");if(!fin){cout<<"cannpt open file!"<<endl;exit(0);}for(i=0;i<N;i++)for(j=0;j<N;j++){fin>>c[i][j];}fin.close();cout<<"最小费用为:\n";cout<<traveling_salesman(c,N,ad)<<endl;cout<<"回路顶点邻接表登记情况为:"<<endl;cout<<"\t";for(i=0;i<N;i++)cout<<i<<"\t";cout<<endl;cout<<"ad:\t";for(i=0;i<N;i++)cout<<ad[i]<<"\t";cout<<endl;
}

fiel(1.text):

运行结果:

货郎担问题(分支限界法)相关推荐

  1. 利用分支限界法解决01背包和货郎担问题

    利用分支限界法解决01背包和货郎担问题详细步骤 原文链接:https://www.cnblogs.com/chihaoyuIsnotHere/p/10007086.html

  2. 算法设计与分析-TSP六种方法-贪心算法(最近邻点、最短链接)、蛮力法、动态规划法、回溯法、分支限界法、模拟退火

    旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径, ...

  3. 算法笔记之分支限界法

    广度优先 广度优先搜索,其实就是层次遍历,程序采用队列来实现. 算法思想 从根开始,常以BF或以最小耗费(即最大收益)优先的方式搜索问题的解空间树.首先将根结点加入活结点表,接着从活结点表中取出根结点 ...

  4. 货郎担问题TSP(dp解法)

    货郎担问题也叫旅行商问题,即TSP问题(Traveling Salesman Problem),是数学领域中著名问题之一. 题目背景 有n个城市,用1,2,-,n表示,城i,j之间的距离为dij,有一 ...

  5. 分支界限算法【0-1背包问题】按照优先队列式(LC)分支限界法求解0-1背包问题, 并给出限界函数,并画出该实例的状态空间树。

    目   录 回溯算法[0-1背包问题] 分支界限算法[0-1背包问题] 作业题(期末考试必考) 小结 回溯算法[0-1背包问题] 分支界限算法[0-1背包问题] 解决思路:采用优先队列式分支限界 Ø ...

  6. 分支限界法实现最优装载c++_分支限界法

    晓强Deep Learning的读书分享会,先从这里开始,从大学开始.大家好,我是晓强,计算机科学与技术专业研究生在读.我会不定时的更新我的文章,内容可能包括深度学习入门知识,具体包括CV,NLP方向 ...

  7. 回溯法(深度优先)剪枝和分支限界法(宽度优先)剪枝对比:01背包问题

    限界函数: CurValue + rest <= BestValue 回溯法(深度优先)剪枝 # 递归方式 class pack_01_back_prune_test: def __init__ ...

  8. 分支限界法:单源最短路径--dijkstra算法

    单源最短路径–dijkstra算法 前面已经多次介绍过dijkstra算法是贪心算法,是动态规划,实际上可以从分支限界的角度来理解: 分支限界法 分支限界法,实际上就是回溯法,一般意义的回溯法是基于深 ...

  9. 五大常用算法之五:分支限界法

    http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741378.html 一.基本描述 类似于回溯法,也是一种在问题的解空间树T上搜索问题解的 ...

最新文章

  1. 独家 | creditR 的基于实践的导论:一个神奇的改良信用风险评分和验证的R包(附代码)...
  2. java transient关键字
  3. C++引用计数(reference counting)技术简介(2)
  4. C++11 非成员函数begin()、end()
  5. C#实现基于ffmpeg加虹软的人脸识别
  6. 7 位 CEO 创业自述:你熬过人生中最黑暗时刻的经历,是你成为强者的必然选择...
  7. 当我在做技术管理时,我在做什么?
  8. 快速排名系统询火星推荐_seo排名工具推荐10火星:比较好用的SEO长尾关键词
  9. 【Linux】——用户账号和组账号
  10. 眼睛怎么画?怎样才能画好人物的眼睛?
  11. oracle批量将id更新为uuid,oracle批量新增更新数据
  12. C++键盘记录器源码
  13. 【Java】Callable 接口
  14. 为什么不使用多线程?
  15. SQL下三种执行CMD命令的方法
  16. 2003服务器 临时文件,#Excel自动保存在哪#office 2003未保存的临时文件在哪个目录里?...
  17. 有限差分法-一维波动方程及其Matlab程序实现
  18. 回顾2016年存储市场发展 解析产品涨价为何如此逆天
  19. Oracle EBS财务模块(四)账套
  20. Redhat 7 下Mysql8.0.19安装配置图文详解(配合使用 centos YUM源)

热门文章

  1. Caché SQL 高性能优化
  2. AIRIOT物联网低代码平台如何配置交通部JT-808协议?
  3. 基于随机无迹σ变异的改进HHO算法
  4. PMP证书对非项目管理者有意义吗?
  5. 当代人类不可或缺的至宝—WiFi
  6. 基于帧间频域分析的视频篡改检测
  7. 玩转亚马逊 AWS IoT(1): IoT 业务梳理
  8. java生成word样式变形的解决方案(freemarker生成word的样式不对)
  9. 海通证券否认获批试点 融资融券再度忽悠券商股
  10. 【剁手】科技发烧友最爱的产品,光是看看就想剁手!