/*
文件名:
BoundleSalesMan.h
限界函数法
*/
#pragma once
#include “salesman.h”
#include <vector>
#include “Node.h”
class BoundSalesMan :
public SalesMan
{
protected:
int SetIMatrix(int i,int k,vector<vector<int> > & im);//
生成第
i
点的规约矩阵
,
并返回约数
,k
点为其父结点
int Cost(vector<int> A); //
获取
A
中保存的路径的路径长度
int SimMatrix(vector< vector<int> > & m); //
将
m
规约
public:
void Travel();
};
/*
文件名:
BoundleSalesMan.cpp
限界函数法
*/
#include “StdAfx.h”
#include “BoundSalesMan.h”
#include “Node.h”
#include <queue>
#include <vector>
int BoundSalesMan::SimMatrix(vector<vector<int> > & m)
//
将
m
规约
{
int result=0;
int col=(int)m.size()-1;
bool boolMax,boolZone;
//
对行进行规约
for (int i=0;i<=col;i++)
{
boolMax=true,
boolZone=false;
for (int j=0;j<=col;j++)
{
boolMax=boolMax && (m[i][j]==MAXNUM); //
所有都是无穷大
boolZone=boolZone || (m[i][j]==0) ; //
是否有一个是
0
}
if ((boolMax) || (boolZone))
//
如果本行所有数据元素都是无穷大,或者有一个是
0
,本行已经规约
continue;//
继续下一行
else //
否则
{
//
从本行中找到最小的一个值,减去他,约数加上这个值
int min=m[i][0];
for (int k=1;k<=col;k++)
{
if (min>m[i][k])
min=m[i][k];
}
for (int k=0;k<=col;k++)
{
if (m[i][k]!=MAXNUM) //
如果是无穷值,则不变
m[i][k]-=min;
}
result+=min;
}
}
//
对列进行规约
for (int i=0;i<=col;i++)
{
boolMax=true,
boolZone=false;
for (int j=0;j<=col;j++)
{
boolMax=boolMax && (m[j][i]==MAXNUM); //
所有都是无穷大
boolZone=boolZone || (m[j][i]==0) ; //
是否有一个是
0
}
if ((boolMax) || (boolZone))
//
如果本列所有数据元素都是无穷大,或者有一个是
0
,本列已经规约
continue;//
继续下一列
else //
否则
{
//
从本列中找到最小的一个值,减去他,约数加上这个值
int min=m[0][i];
for (int k=1;k<=col;k++)
{
if (min>m[k][i])
min=m[k][i];
}
for (int k=0;k<=col;k++)
{
if (m[k][i]!=MAXNUM) //
如果是无穷值,则不变
m[k][i]-=min;
}
result+=min;
}
}
return result;
}
int BoundSalesMan::SetIMatrix(int i,int k,vector<vector<int> > & im)
//
生成第
i
点的规约矩阵
{
int cols=im.size()-1;
//
先将
k
行
和
i
列置为无穷
/
for (int j=0;j<=cols;j++)
{
im[k][j]=MAXNUM;
im[j][i]=MAXNUM;
}
//
再将
i
行
0
列置为无穷
im[i][0]=MAXNUM;
//
再进行规约,记录规约值
return SimMatrix(im);
}
int BoundSalesMan::Cost(vector<int> A)
//
获取
A
中保存的路径的路径长度
{
int i=A.size();
int sum=matrix[0][A[0]];//
先求从
0
到第一个点的距离
for (unsigned int i=1;i<A.size();i++)
{
sum+=matrix[A[i-1]][A[i]];
}
sum+=matrix[A[i-1]][0];//
再加上最后一个点到
0
点的距离
return sum;
}
void BoundSalesMan::Travel()
{
path.clear();
vector<vector<int> > simpleM=matrix; //0
点的规约矩阵
int n0=SimMatrix(simpleM);
int cols=matrix.size()-1;
priority_queue<Node> p;
Node firstNode(n0,0,0,path,simpleM);
p.push(firstNode); //0
结点入队列
Node node;
while (! p.empty() && p.top().level<cols )
{
node=p.top();
p.pop();
for (int i=1;i<=cols;i++)
{
for (int j=0;j<node.states.size();j++)
{
if (i==node.states[j]) //
路径里有这个点了
break;
}
if (j<node.states.size())
continue;
//
否则
simpleM=node.m;
int tmp=node.num;
tmp+=simpleM[node.position][i];
tmp+=SetIMatrix(i,node.position ,simpleM); //
对第
i
点的矩阵进行处理
vector<int> tmpPath=node.states;
tmpPath.push_back(i);
Node newNode(tmp,node.level+1,i,tmpPath,simpleM);
p.push(newNode);
}
}
path=p.top().states;
cout<<“Bound MinValue:”<<Cost(path)<<endl;
PrintPath();
}
/*
文件名:
SalesMan
。
H
货郎担基类头文件
*/
#pragma once
#include <vector>
#include <fstream>
using namespace std;
class SalesMan
{
protected:
enum{MAXNUM=999}; //
最大值设为无穷大
vector<vector<int> > matrix; //
对应的邻接矩阵
vector<int> path; //
记录走过的最小成本路径
int minValue;//
最小路径长度
public:
SalesMan();
virtual ~SalesMan(){matrix.clear();path.clear();}
void PrintMatrix(); //
打印矩阵值
void PrintPath(); //
打印路径
virtual void Travel(){}; //
主要寻找路径的函数,将在子类里面实现
};
/*
文件名:
SalesMan
。
Cpp
货郎担基类源文件
*/
#include “StdAfx.h”
#include “SalesMan.h”
SalesMan::SalesMan() //
构造函数,从文件中读取数值,生成图的邻接矩阵,
{//
认为矩阵结点从
0
开始
fstream fin(“in.txt”);
if (!fin)
{
cerr<<“file open failed!”<<endl;
return;
}
int n;
fin>>n;
path.resize(n-1); //
路径记录中间的那些结点
//
从文件里取值
for (int i=0;i<n;i++)
{
vector<int> col;
for (int j=0;j<n;j++)
{
int num;
fin>>num;
col.push_back(num);
}
matrix.push_back(col);
}
fin.close();
}
void SalesMan::PrintPath()
{
cout<<0<<“/t”;
for (unsigned int i=0;i<path.size();i++)
cout<<path[i]<<“/t”;
cout<<“0″<<endl;
}
void SalesMan::PrintMatrix()
{
int n=(int)matrix.size();
for (int i=0;i<n;i++)
{
for (int j=0;j<n;j++)
cout<<matrix[i][j]<<“/t”;
cout<<endl;
}
}
/*
文件名:
Node.h
为
BoundSalesMan
所调用,结点数据结构
*/
#pragma once
#include <vector>
using namespace std;
struct Node
{
public:
int num;//
约数
int level; //
层级
int position; //
当前结点
vector<vector<int> > m; //
当前结点的矩阵
vector<int> states; //
当前路径状态集
Node(){};
Node(int n,int l,int position,vector<int> path,vector<vector<int> > mValue);
bool operator< (const Node & B)const
{
return num>B.num;
}
};
/*
文件名:
Node.cpp
为
BoundSalesMan
所调用,结点数据结构的实现
*/
#include “StdAfx.h”
#include “Node.h”
Node::Node(int n,int l,int pos,vector<int> path,vector<vector<int> > mValue)
{
num=n; level=l; position=pos; states=path; m=mValue;
}
分支限界求解货郎担/旅行商问题
原文作者:分支限界法
原文地址: https://blog.csdn.net/ly33854983/article/details/1705142
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/ly33854983/article/details/1705142
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。