分支限界求解货郎担/旅行商问题
2007-07-24 13:16
344 查看
[align=left]/* 文件名:BoundleSalesMan.h 限界函数法 */[/align]
[align=left]#pragma once[/align]
[align=left]#include "salesman.h"[/align]
[align=left]#include <vector>[/align]
[align=left]#include "Node.h"[/align]
[align=left]class BoundSalesMan :[/align]
[align=left] public SalesMan[/align]
[align=left]{[/align]
[align=left]protected:[/align]
[align=left] int SetIMatrix(int i,int k,vector<vector<int> > & im);//生成第i点的规约矩阵,并返回约数,k点为其父结点[/align]
[align=left] int Cost(vector<int> A); //获取A中保存的路径的路径长度[/align]
[align=left] int SimMatrix(vector< vector<int> > & m); //将m规约[/align]
[align=left]public: [/align]
[align=left] void Travel();[/align]
[align=left]};[/align]
[align=left]/* 文件名:BoundleSalesMan.cpp 限界函数法 */[/align]
[align=left]#include "StdAfx.h"[/align]
[align=left]#include "BoundSalesMan.h"[/align]
[align=left]#include "Node.h"[/align]
[align=left]#include <queue>[/align]
[align=left]#include <vector>[/align]
[align=left]int BoundSalesMan::SimMatrix(vector<vector<int> > & m)[/align]
[align=left]//将m规约[/align]
[align=left]{[/align]
[align=left] int result=0;[/align]
[align=left] int col=(int)m.size()-1;[/align]
[align=left] bool boolMax,boolZone;[/align]
[align=left] //对行进行规约[/align]
[align=left] for (int i=0;i<=col;i++)[/align]
[align=left] {[/align]
[align=left] boolMax=true,[/align]
[align=left] boolZone=false;[/align]
[align=left] for (int j=0;j<=col;j++)[/align]
[align=left] {[/align]
[align=left] boolMax=boolMax && (m[i][j]==MAXNUM); //所有都是无穷大[/align]
[align=left] boolZone=boolZone || (m[i][j]==0) ; //是否有一个是0[/align]
[align=left] }[/align]
[align=left] if ((boolMax) || (boolZone))[/align]
[align=left] //如果本行所有数据元素都是无穷大,或者有一个是0,本行已经规约[/align]
[align=left] continue;//继续下一行[/align]
[align=left] else //否则[/align]
[align=left] {[/align]
[align=left] //从本行中找到最小的一个值,减去他,约数加上这个值[/align]
[align=left] int min=m[i][0];[/align]
[align=left] for (int k=1;k<=col;k++)[/align]
[align=left] {[/align]
[align=left] if (min>m[i][k])[/align]
[align=left] min=m[i][k];[/align]
[align=left] }[/align]
[align=left] for (int k=0;k<=col;k++)[/align]
[align=left] {[/align]
[align=left] if (m[i][k]!=MAXNUM) //如果是无穷值,则不变[/align]
[align=left] m[i][k]-=min;[/align]
[align=left] }[/align]
[align=left] result+=min;[/align]
[align=left] }[/align]
[align=left] } [/align]
[align=left] //对列进行规约[/align]
[align=left] for (int i=0;i<=col;i++)[/align]
[align=left] {[/align]
[align=left] boolMax=true,[/align]
[align=left] boolZone=false;[/align]
[align=left] for (int j=0;j<=col;j++)[/align]
[align=left] {[/align]
[align=left] boolMax=boolMax && (m[j][i]==MAXNUM); //所有都是无穷大[/align]
[align=left] boolZone=boolZone || (m[j][i]==0) ; //是否有一个是0[/align]
[align=left] }[/align]
[align=left] if ((boolMax) || (boolZone))[/align]
[align=left] //如果本列所有数据元素都是无穷大,或者有一个是0,本列已经规约[/align]
[align=left] continue;//继续下一列[/align]
[align=left] else //否则[/align]
[align=left] {[/align]
[align=left] //从本列中找到最小的一个值,减去他,约数加上这个值[/align]
[align=left] int min=m[0][i];[/align]
[align=left] for (int k=1;k<=col;k++)[/align]
[align=left] {[/align]
[align=left] if (min>m[k][i])[/align]
[align=left] min=m[k][i];[/align]
[align=left] }[/align]
[align=left] for (int k=0;k<=col;k++)[/align]
[align=left] {[/align]
[align=left] if (m[k][i]!=MAXNUM) //如果是无穷值,则不变[/align]
[align=left] m[k][i]-=min;[/align]
[align=left] }[/align]
[align=left] result+=min;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] return result;[/align]
[align=left]}[/align]
[align=left]int BoundSalesMan::SetIMatrix(int i,int k,vector<vector<int> > & im)[/align]
[align=left]//生成第i点的规约矩阵[/align]
[align=left]{[/align]
[align=left] int cols=im.size()-1;[/align]
[align=left] //先将k行和i列置为无穷/[/align]
[align=left] for (int j=0;j<=cols;j++)[/align]
[align=left] {[/align]
[align=left] im[k][j]=MAXNUM; [/align]
[align=left] im[j][i]=MAXNUM;[/align]
[align=left] }[/align]
[align=left] //再将i行0列置为无穷[/align]
[align=left] im[i][0]=MAXNUM; [/align]
[align=left] //再进行规约,记录规约值[/align]
[align=left] return SimMatrix(im);[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]int BoundSalesMan::Cost(vector<int> A)[/align]
[align=left]//获取A中保存的路径的路径长度[/align]
[align=left]{[/align]
[align=left] int i=A.size();[/align]
[align=left] int sum=matrix[0][A[0]];//先求从0到第一个点的距离[/align]
[align=left] for (unsigned int i=1;i<A.size();i++)[/align]
[align=left] {[/align]
[align=left] sum+=matrix[A[i-1]][A[i]];[/align]
[align=left] }[/align]
[align=left] sum+=matrix[A[i-1]][0];//再加上最后一个点到0点的距离[/align]
[align=left] return sum;[/align]
[align=left]}[/align]
[align=left]void BoundSalesMan::Travel()[/align]
[align=left]{[/align]
[align=left] path.clear();[/align]
[align=left] vector<vector<int> > simpleM=matrix; //0点的规约矩阵[/align]
[align=left] int n0=SimMatrix(simpleM);[/align]
[align=left] int cols=matrix.size()-1; [/align]
[align=left] priority_queue<Node> p;[/align]
[align=left] Node firstNode(n0,0,0,path,simpleM); [/align]
[align=left] p.push(firstNode); //0结点入队列[/align]
[align=left] Node node;[/align]
[align=left] while (! p.empty() && p.top().level<cols )[/align]
[align=left] {[/align]
[align=left] node=p.top();[/align]
[align=left] p.pop();[/align]
[align=left] for (int i=1;i<=cols;i++)[/align]
[align=left] {[/align]
[align=left] for (int j=0;j<node.states.size();j++)[/align]
[align=left] {[/align]
[align=left] if (i==node.states[j]) //路径里有这个点了[/align]
[align=left] break;[/align]
[align=left] }[/align]
[align=left] if (j<node.states.size()) [/align]
[align=left] continue; [/align]
[align=left] //否则[/align]
[align=left] simpleM=node.m;[/align]
[align=left] int tmp=node.num;[/align]
[align=left] tmp+=simpleM[node.position][i];[/align]
[align=left] tmp+=SetIMatrix(i,node.position ,simpleM); //对第i点的矩阵进行处理 vector<int> tmpPath=node.states;[/align]
[align=left] tmpPath.push_back(i);[/align]
[align=left] Node newNode(tmp,node.level+1,i,tmpPath,simpleM);[/align]
[align=left] p.push(newNode);[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] path=p.top().states;[/align]
[align=left] cout<<"Bound MinValue:"<<Cost(path)<<endl;[/align]
[align=left] PrintPath();[/align]
[align=left]}[/align]
[align=left]/* 文件名:SalesMan。H 货郎担基类头文件 */[/align]
[align=left]#pragma once[/align]
[align=left]#include <vector>[/align]
[align=left]#include <fstream>[/align]
[align=left]using namespace std;[/align]
[align=left]class SalesMan[/align]
[align=left]{[/align]
[align=left]protected:[/align]
[align=left] enum{MAXNUM=999}; //最大值设为无穷大[/align]
[align=left] vector<vector<int> > matrix; //对应的邻接矩阵[/align]
[align=left] vector<int> path; //记录走过的最小成本路径[/align]
[align=left] int minValue;//最小路径长度[/align]
[align=left]public:[/align]
[align=left] SalesMan();[/align]
[align=left] virtual ~SalesMan(){matrix.clear();path.clear();}[/align]
[align=left] void PrintMatrix(); //打印矩阵值[/align]
[align=left] void PrintPath(); //打印路径[/align]
[align=left] virtual void Travel(){}; //主要寻找路径的函数,将在子类里面实现[/align]
[align=left]};[/align]
[align=left]/* 文件名:SalesMan。Cpp 货郎担基类源文件 */[/align]
[align=left]#include "StdAfx.h"[/align]
[align=left]#include "SalesMan.h"[/align]
[align=left]SalesMan::SalesMan() //构造函数,从文件中读取数值,生成图的邻接矩阵,[/align]
[align=left]{//认为矩阵结点从0开始[/align]
[align=left] fstream fin("in.txt");[/align]
[align=left] if (!fin)[/align]
[align=left] { [/align]
[align=left] cerr<<"file open failed!"<<endl;[/align]
[align=left] return;[/align]
[align=left] }[/align]
[align=left] int n;[/align]
[align=left] fin>>n;[/align]
[align=left] path.resize(n-1); //路径记录中间的那些结点[/align]
[align=left] //从文件里取值[/align]
[align=left] for (int i=0;i<n;i++)[/align]
[align=left] {[/align]
[align=left] vector<int> col; [/align]
[align=left] for (int j=0;j<n;j++)[/align]
[align=left] {[/align]
[align=left] int num;[/align]
[align=left] fin>>num;[/align]
[align=left] col.push_back(num);[/align]
[align=left] } [/align]
[align=left] matrix.push_back(col);[/align]
[align=left] }[/align]
[align=left] fin.close();[/align]
[align=left]}[/align]
[align=left]void SalesMan::PrintPath()[/align]
[align=left]{[/align]
[align=left] cout<<0<<"/t";[/align]
[align=left] for (unsigned int i=0;i<path.size();i++)[/align]
[align=left] cout<<path[i]<<"/t";[/align]
[align=left] cout<<"0"<<endl;[/align]
[align=left]}[/align]
[align=left]void SalesMan::PrintMatrix()[/align]
[align=left]{[/align]
[align=left] int n=(int)matrix.size();[/align]
[align=left] for (int i=0;i<n;i++)[/align]
[align=left] {[/align]
[align=left] for (int j=0;j<n;j++)[/align]
[align=left] cout<<matrix[i][j]<<"/t"; [/align]
[align=left] cout<<endl;[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]/* 文件名:Node.h 为BoundSalesMan所调用,结点数据结构 */[/align]
[align=left]#pragma once[/align]
[align=left]#include <vector>[/align]
[align=left]using namespace std;[/align]
[align=left]struct Node[/align]
[align=left]{[/align]
[align=left]public:[/align]
[align=left] int num;//约数[/align]
[align=left] int level; //层级[/align]
[align=left] int position; //当前结点[/align]
[align=left] vector<vector<int> > m; //当前结点的矩阵[/align]
[align=left] vector<int> states; //当前路径状态集[/align]
[align=left] Node(){};[/align]
[align=left] Node(int n,int l,int position,vector<int> path,vector<vector<int> > mValue);[/align]
[align=left] bool operator< (const Node & B)const[/align]
[align=left] {[/align]
[align=left] return num>B.num;[/align]
[align=left] }[/align]
[align=left]};[/align]
[align=left]/* 文件名:Node.cpp 为BoundSalesMan所调用,结点数据结构的实现 */[/align]
[align=left]#include "StdAfx.h"[/align]
[align=left]#include "Node.h"[/align]
[align=left]Node::Node(int n,int l,int pos,vector<int> path,vector<vector<int> > mValue)[/align]
[align=left]{[/align]
[align=left] num=n; level=l; position=pos; states=path; m=mValue;[/align]
[align=left]}[/align]
相关文章推荐
- 分支限界求解货郎担/旅行商问题
- 分支限界求解TSP问题
- KM算法结合分支定界求解旅行商问题
- 一个分支限界的旅行商求解
- 一个分支限界的旅行商求解
- 过河卒问题的动态规划求解(分支限界或者回溯过于耗时)
- 分支限界解决旅行商tsp问题
- 遗传算法求解旅行商问题
- (C语言)分支界限法求解旅行商(TSP)问题
- 分支限界---->15-谜问题
- 用分支定界的方法求解变形的背包问题(c++版本)
- 分支限界问题分析--和回溯法的区别以及在何时用的区别
- [置顶] 蚁群算法求解旅行商问题 python
- 遗传算法求解旅行商(TSP)问题
- 遗传算法求解旅行商问题
- 利用遗传算法求解旅行商问题
- 模拟退火算法求解旅行商问题
- 分支限界---->装载问题
- 模拟退火算法求解旅行商问题
- 用分支限界法解决人员安排问题(Personnel assignment problem)