⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 brandy3.cpp

📁 本程序用分支界限方法解决TSP问题
💻 CPP
字号:
//分支限界法求解TSP问题的程序
#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
using namespace std;

//定义相关结构体
typedef struct node_data      //结点数据结构
{
	float c[20][20];          /*费用矩阵*/
	int row_init[20];         /*费用矩阵的当前行映射为原始行*/
	int col_init[20];         /*费用矩阵的当前列映射为原始列*/
	int row_cur[20];          /*费用矩阵的原始行映射为当前行*/
	int col_cur[20];          /*费用矩阵的原始列映射为当前列*/
	int ad[20];               /*回路顶点邻接表*/
	int k;                    /*当前费用矩阵的阶*/
	float w;                  /*结点的下界*/
}NODE;

typedef struct                /*堆结构数据*/
{
	NODE *p;                  /*指向结点元素的指针*/
	float w;                  /*所指向结点的下界,堆元素的关键字*/ 
}HEAP;

//主要函数申明部分
float row_min(NODE *node,int row,float &second);
float col_min(NODE *node,int col,float &second);
float array_red(NODE *node);
float edge_sel (NODE *node,int &vk,int &vl);
void del_rowcol(NODE *node,int vk,int vl);
void edge_byp(NODE *node,int vk, int vl);
NODE *initial(float c[20][20],int n);
void insert(HEAP *&heap,int &n_heap,HEAP z);
HEAP delete_min(HEAP *&heap,int &n_heap);

//主函数开始
int main()
{
    int n=20;
	int ad[20],path[20];
	float c[20][20];
	float max_distance, min_distance;
	string filename="distance.txt";
	ifstream sensor;

	sensor.open(filename.c_str());             //打开文件读取距离数据信息
	if(sensor.fail())
	{
		cout<<"Error opening input file\n";
	}
	else 
	{
		sensor>>max_distance>>min_distance;    //没有到达文件末尾时循环读取数据

		while(!sensor.eof())
		{
			for(int i=0;i<20;i++)
			{
				for(int j=0;j<20;j++)
				{
					sensor>>c[i][j];
				}
				c[i][i]=max_distance+1;
			}
		}
	}                                         //读取距离信息结束

	int i,j,vk,vl;
    float d,w=0;
	NODE *xnode;
	NODE *ynode;
	NODE *znode;
	int n_heap=0;
    HEAP *heap=new HEAP[50*30];
    HEAP  x,y,z;

    xnode=initial(c,n);
    xnode->w=array_red(xnode);
    while(xnode->k!=0)
	{
		d=edge_sel(xnode,vk,vl);
        znode=new NODE;
        *znode =*xnode;
        znode->c[vk][vl]=max_distance+1;
        array_red(znode);
        znode->w=xnode->w+d;
        z.w=znode->w;
        z.p=znode;
        insert(heap,n_heap,z);  
        ynode=new NODE;
        *ynode=*xnode;
        edge_byp(ynode,vk,vl);
        del_rowcol(ynode,vk,vl);
        ynode->w=array_red(ynode);
        ynode->w+=xnode->w;
        y.w=ynode->w;
        y.p=ynode;

        if(ynode->k==2)
		{
			if(ynode->c[0][0]==0)
			{
				ynode->ad[ynode->row_init[0]]=ynode->col_init[1];
                ynode->ad[ynode->row_init[1]]=ynode->col_init[0];
			}
            else
			{
			    ynode->ad[ynode->row_init[0]]=ynode->col_init[0];
                ynode->ad[ynode->row_init[1]]=ynode->col_init[1];
			}
            ynode->k=0;
		}
        insert (heap,n_heap,y);
        delete xnode;
        x=delete_min(heap,n_heap);  
        xnode=x.p;
	}
    
    w=xnode->w;

    for(i=0;i<n;i++)               //保存邻接表
		ad[i]=xnode->ad[i];
	
    delete xnode;

	for (i=0;i<n_heap;i++)         //释放结点数据空间
	{
		delete heap->p;
		heap--;
	}
	heap++;

    delete []heap;                //释放堆空间

	int t=0,k=1;                  //将邻接表转化为遍历城市的顺序列表,保存在path[]中
	path[0]=0;
	while(k<n)
	{
		j=t;
		t=ad[j];
		path[k]=t;
		k++;
	}                            

	cout<<"the result of the path:"<<endl;        //输出最优遍历城市顺序的结果,转化为A、B的形式

	for(j=0;j<20;j++)
	{
		cout<<char(path[j]+65)<<' ';
	}

	cout<<endl<<"the total length is: "<<w<<endl; //输出最短路程的值


	return 0;
}                   //主函数结束

/**********************************函数定义部分***********************************/

//返回由指针node所指向节点费用矩阵中第row行最小值,并把次小值回送与引用变量second中
float row_min(NODE *node,int row,float &second)
{
	float temp;
    int i;
    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];
	}
    return temp;
}
//返回由指针node所指向节点费用矩阵中第col列最小值,并把次小值回送与引用变量second中
float col_min(NODE *node,int col, float &second)
{
	float temp;
    int i;
    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];
     }
  return temp;
}
//归约指针node指向的节点的费用矩阵 返回值为归约常数
float array_red(NODE *node)
{
  int i,j;
  float temp,temp1,sum=0;
  for(i=0;i<node->k;i++)
  {
	  temp=row_min(node,i,temp1);
      for (j=0;j<node->k;j++)
		  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++)
		  node->c[i][j] -=temp;
      sum +=temp;
  }
  return sum;
}
//计算dkl 并且搜索分支的边 返回dkl的值
float edge_sel(NODE *node,int &vk,int &vl)
{
  int i,j;
  float temp,d=0;
  float *row_value=new float[node->k];
  float *col_value=new float[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++)
  {
	  for(j=0;j<node->k;j++)
	  {
		  if (node->c[i][j]==0)
		  {
			  temp=row_value[i]+col_value[j];
		      if(temp>d)
			  {
				  d=temp; vk=i;vl=j;
			  }
		  }
	  }
  }
  delete row_value;
  delete col_value;
  return d;
}
//del_rowcol(NODE *node,int vk,int vl)删除费用矩阵当前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];
    node->row_cur[vk1]=-1;
    for (i=vk1+1;i<20;i++)
		node->row_cur[i]--;//
    vl1=node->col_init[vl];
    node->col_cur[vl1]=-1;
	for (i=vl1+1;i<20;i++)
		node->col_cur[i]--;
    for (i=vk;i<node->k-1;i++)
		node->row_init[i]=node->row_init[i+1];
    for(i=vl;i<node->k-1;i++)
		node->col_init[i]=node->col_init[i+1];
    node->k--;
}
//把vk vl表示的边登记到顶点邻接表 并旁路矩阵中有关的边
void edge_byp(NODE *node,int vk, int vl)
{
	int i,j,k,l;
    vk=node->row_init[vk];
    vl=node->col_init[vl];
    node->ad[vk]=vl;
    for (i=0;i<20;i++)
	{
		j=i;
        while (node->ad[j]!=-1)
        j=node->ad[j];
        if(i!=j)
		{
			l=node->row_cur[j];
            k=node->col_cur[i];
            if((k>0)&&(l>0))
            node->c[l][k]=100;   //以后要改进的地方 100是个特殊值
		}
	}
}
//初始化函数
NODE *initial(float c[20][20],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 insert(HEAP *&heap,int &n_heap,HEAP z)
{
	HEAP *temp;
	int k=n_heap;
	if(k==0) 
	{
		*heap=z;
	}
	else
	{
		temp=heap;
	    while(heap->w<z.w&&k>0)
		{
			*(heap+1)=*heap;
		    k--;
		    if(k>0)  heap--;
		}
	    if(k>0)  heap++;
	    *heap=z;
        heap=temp+1;
	}
    n_heap++;
}

//删除堆栈头结点函数
HEAP delete_min(HEAP *&heap,int &n_heap)
{
	HEAP temp;
	temp=(*heap);
	heap--;
	n_heap--;
	return temp;
}
	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -