现在的位置: 首页 > 综合 > 正文

采用openMP并行方法,实现用分支界限法解决的旅行售货员问题

2014年02月13日 ⁄ 综合 ⁄ 共 3798字 ⁄ 字号 评论关闭
#include "StdAfx.h"
//源代码:
#include <stdio.h> 
#include <malloc.h>
#include <stdlib.h>
#include <time.h>
#include <omp.h>


#define NoEdge 1000
struct MinHeapNode
{
    int lcost; //子树费用的下界
    int cc; //当前费用
    int rcost; //x[s:n-1]中顶点最小出边费用和
    int s; //根节点到当前节点的路径为x[0:s]
    int *x; //需要进一步搜索的顶点是//x[s+1:n-1]
struct MinHeapNode *next;
};
int n; //图G的顶点数
int **a; //图G的邻接矩阵
//int NoEdge; //图G的无边标记
int cc; //当前费用 
int bestc; //当前最小费用
MinHeapNode* head = 0; /*堆头*/
MinHeapNode* lq = 0; /*堆第一个元素*/
MinHeapNode* fq = 0; /*堆最后一个元素*/
clock_t start, finish;  
double  duration;  


int DeleteMin(MinHeapNode*&E)
{
MinHeapNode* tmp = NULL;
tmp = fq;
// w = fq->weight ;
E = fq;
if(E == NULL)
return 0;
head->next = fq->next; /*一定不能丢了链表头*/
fq = fq->next;
// free(tmp) ;
return 0;
}
int Insert(MinHeapNode* hn)
{
if(head->next == NULL)
{
head->next = hn; //将元素放入链表中
fq = lq = head->next; //一定要使元素放到链中
}
else
{
MinHeapNode *tmp = NULL;
tmp = fq;
if(tmp->cc > hn->cc)
{
hn->next = tmp;
head->next = hn;
fq = head->next; /*链表只有一个元素的情况*/
}
else
{
for(; tmp != NULL;)
{
if(tmp->next != NULL && tmp->cc > hn->cc)
{
hn->next = tmp->next;
tmp->next = hn;
break;
}
tmp = tmp->next;
}
}
if(tmp == NULL)
{
lq->next = hn;
lq = lq->next;
}
}
return 0;
}
int BBTSP(int v[])
{//解旅行售货员问题的优先队列式分支限界法
/*初始化最优队列的头结点*/
head = (MinHeapNode*)malloc(sizeof(MinHeapNode));
head->cc = 0;
head->x = 0;
head->lcost = 0;
head->next = NULL;
head->rcost = 0;
head->s = 0;
int i = 0;
int numThreads = 0;
int *MinOut = new int[n + 1]; /*定义定点i的最小出边费用*/
//计算MinOut[i]=顶点i的最小出边费用
int MinSum = 0;//最小出边费用总合


printf("please input the number of threads : ");
scanf_s("%d",&numThreads);


start = clock();  //开始时间


for(i = 1; i <= n; i++)
{
int Min = NoEdge; /*定义当前最小值*/
for(int j = 1; j <= n; j++)
if(a[i][j] != NoEdge && /*当定点i,j之间存在回路时*/ 
(a[i][j] < Min || Min == NoEdge)) /*当顶点i,j之间的距离小于Min*/
Min = a[i][j]; /*更新当前最小值*/
if(Min == NoEdge)
return NoEdge;//无回路
MinOut[i] = Min; /*顶点i的最小出边费用*/
MinSum += Min; /*最小出边费用的总和*/
}
MinHeapNode *E = 0;
E = (MinHeapNode*)malloc(sizeof(MinHeapNode));
E->x = new int[n];
// E.x=new int[n];
for(i = 0; i < n; i++)
E->x[i] = i + 1;
E->s = 0;
E->cc = 0;
E->rcost = MinSum;
E->next = 0; //初始化当前扩展节点
int bestc = NoEdge; /*记录当前最小值*/
//搜索排列空间树
while(E->s < n - 1)
{//非叶结点
if(E->s == n - 2)
{//当前扩展结点是叶结点的父结点
if(a[E->x[n - 2]][E->x[n - 1]] != NoEdge && /*当前要扩展和叶节点有边存在*/
a[E->x[n - 1]][1] != NoEdge && /*当前页节点有回路*/
(E->cc + a[E->x[n - 2]][E->x[n - 1]] + a[E->x[n - 1]][1] < bestc /*该节点相应费用小于最小费用*/
|| bestc == NoEdge))
{
bestc = E->cc + a[E->x[n - 2]][E->x[n - 1]] + a[E->x[n - 1]][1]; /*更新当前最新费用*/
E->cc = bestc;
E->lcost = bestc;
E->s++;
E->next = NULL;
Insert(E); /*将该页节点插入到优先队列中*/
}
else
free(E->x);//该页节点不满足条件舍弃扩展结点
}
else
{//产生当前扩展结点的儿子结点

omp_set_num_threads(numThreads);
#pragma omp parallel for


for(i = E->s + 1; i < n; i++)
if(a[E->x[E->s]][E->x[i]] != NoEdge)
{ /*当前扩展节点到其他节点有边存在*/
//可行儿子结点
int cc = E->cc + a[E->x[E->s]][E->x[i]]; /*加上节点i后当前节点路径*/
int rcost = E->rcost - MinOut[E->x[E->s]]; /*剩余节点的和*/
int b = cc + rcost; //下界
if(b < bestc || bestc == NoEdge)
{//子树可能含最优解,结点插入最小堆
MinHeapNode * N;
N = (MinHeapNode*)malloc(sizeof(MinHeapNode));
N->x = new int[n];
for(int j = 0; j < n; j++)
N->x[j] = E->x[j];
N->x[E->s + 1] = E->x[i];
N->x[i] = E->x[E->s + 1];/*添加当前路径*/
N->cc = cc; /*更新当前路径距离*/
N->s = E->s + 1; /*更新当前节点*/
N->lcost = b; /*更新当前下界*/
N->rcost = rcost;
N->next = NULL;
Insert(N); /*将这个可行儿子结点插入到活结点优先队列中*/
}
}
free(E->x);
}//完成结点扩展
DeleteMin(E);//取下一扩展结点
if(E == NULL)
break; //堆已空
}
if(bestc == NoEdge)
return NoEdge;//无回路
for(i = 0; i < n; i++)
v[i + 1] = E->x[i];//将最优解复制到v[1:n]
while(true)
{//释放最小堆中所有结点
free(E->x);
DeleteMin(E);
if(E == NULL)
break;
}
return bestc;
}
int main()
{
n = 0;
int i = 0;
printf("please input the number of cites : ");
scanf_s("%d", &n);
a = (int**)malloc(sizeof(int*) * (n + 1));
for(i = 1; i <= n; i++)
{
a[i] = (int*)malloc(sizeof(int) * (n + 1));
}
for(i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
/*scanf("%d", &a[i][j]);*/
{
//a[i][j] = (((i + j) * 99) % 14) + 1;
a[i][j] = i+j;
if(i == j)a[i][j]=0;
//printf("%d  ",a[i][j]);
}
//printf("\n");
}
// prev = (int*)malloc(sizeof(int)*(n+1)) ;
int*v = (int*)malloc(sizeof(int) * (n + 1));// MaxLoading(w , c , n) ;
for(i = 1; i <= n; i++)
{
v[i] = 0;
}


bestc = BBTSP(v);
printf("the best path is :");
for(i = 1; i <= n; i++)
{
printf("%d->", v[i]);
}
printf("1\nthe shortest cost is "); 
printf("%d\n", bestc);



finish = clock();  
duration = (double)(finish - start) / CLOCKS_PER_SEC;  
        printf( "the duaration time is :%f seconds\n", duration );  






system("pause");
return 0;
}

抱歉!评论已关闭.