赋权边覆盖问题是图论中的经典问题。

本文详细讨论了禁忌搜索算法求解赋权边覆盖问题的定义、原理及求解思路,在文末给出了实验结果及完整的C++实现代码。

///

///

源程序

(一)最小边覆盖

#include "stdafx.h"#include<iostream>
using namespace std;/控制参数
#define EDGE_NUM  7 //边数量
#define POINT_NUM 6 //顶点数量
#define N_K 2 //K邻域
#define HNUM  4    //禁忌队列长度,队列元素为一可行解对象static  int stepMAX=50;//最大迭代次数,终止条件
static  float GOAL=100;//最优目标值 /主要数据结构定义/
struct EDGE
{
int from;//边起始顶点序号
int to;//边终止顶点序号
float w;//边的权值
};//边结构体数据类型static EDGE elib[EDGE_NUM ];//边数据存储数组
static int plib[POINT_NUM];//顶点序号数据存储数组
static int leb[POINT_NUM ];//顶点覆盖标志数组class vectorE
{
public:int e[EDGE_NUM];//解向量中各边是否被选种标志 int i,j;vectorE(int a[]){for (i=0;i<EDGE_NUM;i++)e[i]=a[i];}vectorE(){for (i=0;i<EDGE_NUM;i++)e[i]=-1;//默认参数下,解向量是非法的标志-1}vectorE(vectorE & VE){for (i=0;i<EDGE_NUM;i++)e[i]=VE.e[i];}int operator==(vectorE VE)//运算符重载{for (i=0,j=0;i<EDGE_NUM;i++){if (e[i]!=VE.e[i])break; else j+=1;}if(j==EDGE_NUM)return 1;else return 0;}void operator=(vectorE VE)//运算符重载{for (i=0;i<EDGE_NUM;i++)e[i]=VE.e[i];}void operator=(int a[])//运算符重载{for (i=0;i<EDGE_NUM;i++)e[i]=a[i];}
vectorE operator-(vectorE VE)运算符重载,返回邻居
{vectorE et=e;for (i=0;i<EDGE_NUM;i++){if (VE.e[i]==1)et.e[i]=1-e[i]; }
return et;
}float WE()
{
float wt=0;
for (i=0;i<EDGE_NUM;i++)
{  wt+=e[i]*elib[i].w;
}
return abs(wt);
}
};//可行解类static vectorE H[HNUM];//禁忌队列
static H_rear=HNUM;//禁忌队列对尾指针
static H_front=HNUM;//禁忌队列对头指针
static H_s=0;//禁忌队列满标志struct N_TABE//邻域索引表结构
{vectorE ve;struct N_TABE * next;
};///禁忌队列操作函数
void H_clear()//禁忌队列初始化
{
vectorE ve;//非法解
int i;
for (i=0;i<HNUM;i++)H[i]=ve;//初始化队列元素,
H_rear=HNUM;//禁忌队列对尾指针
H_front=HNUM;//禁忌队列对头指针
H_s=0;//禁忌队列满标志
}bool H_add( vectorE ve)//入队运算
{if ((H_s==1)&&(H_front==H_rear)){cout<<"队列已满,无法插入!"<<endl;return false;}
H_rear+=1;
if (H_rear==HNUM+1)H_rear=1;
H[H_rear-1]=ve;
H_s=1;//禁忌队列满标志
return true;
}bool H_delete( vectorE & ve)//出队运算,有参数
{vectorE ve_t;//非法解if ((H_s==0)&&(H_front==H_rear)){cout<<"队列已空,无法删除!"<<endl;return false;}
H_front+=1;
if (H_front==HNUM+1)H_front=1;
ve=H[H_front-1];
H[H_front-1]=ve_t;if (H_front==H_rear)H_s=0;
return true;
}bool H_delete( )//出队运算重载,无参数
{vectorE ve_t;//非法解if ((H_s==0)&&(H_front==H_rear)){cout<<"队列已空,无法删除!"<<endl;return false;}
H_front+=1;
if (H_front==HNUM+1)H_front=1;
//ve=H[H_front-1];
H[H_front-1]=ve_t;
if (H_front==H_rear)H_s=0;
return true;
}int H_IsNot(vectorE ve)//测试解对象ve是否在禁忌队列中,若在,返回在队列中的序号,如不在,返回-1
{int i=H_front+1;if (i==HNUM+1)i=1;if ((H_s==0)&&(H_front==H_rear))return -1;else if (i>H_rear){for (;i<=HNUM;i++){if (H[i-1]==ve) return i;}for (i=1;i<=H_rear;i++){if (H[i-1]==ve) return i;}}else{for (;i<=H_rear;i++){if (H[i-1]==ve) return i;}}return -1;
}void H_free(int n)//特赦禁忌队列中序号为n的元素
{
int i;
vectorE ve_t;//非法解
if ((n<0)||(n>HNUM))
{   cout<<"序号非法,不存在特赦元素!"<<endl;return;
}if ((H_s==0)&&(H_front==H_rear)){cout<<"队列为空,不存在特赦元素!"<<endl;return;}if( ((H_front+1)% HNUM)==n) //如果特赦元素为排头元素{H_front+=1;if (H_front==HNUM+1)H_front=1;
//ve=H[H_front-1];H[H_front-1]=ve_t;if (H_front==H_rear)H_s=0;}//如果特赦元素为排头元素else if( H_rear==n) //如果特赦元素为对尾元素{H[H_rear-1]=ve_t;H_rear-=1;if (H_rear==0)H_rear=HNUM;if (H_front==H_rear)H_s=0;}//如果特赦元素为排头元素else{if (n>H_rear){for (i=n;i<=HNUM-1;i++) {H[i-1]=H[i];}H[HNUM-1]=H[0];for (i=1;i<H_rear-1;i++){H[i-1]=H[i];}H_rear-=1;if (H_rear==0)H_rear=HNUM;}else{for (i=n;i<=H_rear-1;i++) {H[i-1]=H[i];}H_rear-=1;if (H_rear==0)H_rear=HNUM;}}
}void H_display()//禁忌对队列显示,用于调试程序
{int i,j,a,b;if ((H_s==0)&&(H_front==H_rear)){cout<<"队列为空,无法显示!"<<endl;return ;}else{a=H_front+1;if (a==HNUM+1)a=1;b=H_rear;if (a>b){for (i=a;i<=HNUM;i++){for(j=0;j<EDGE_NUM;j++)cout<<H[i-1].e[j]<<",";cout<<endl;}
for (i=1;i<=H_rear;i++){for(j=0;j<EDGE_NUM;j++)cout<<H[i-1].e[j]<<",";cout<<endl;}}else{for (i=a;i<=b;i++){for(j=0;j<EDGE_NUM;j++)cout<<H[i-1].e[j]<<",";cout<<endl;}}cout<<"H_front,H_rear,H_s are:"<<H_front<<","<<H_rear<<","<<H_s<<endl;}}/辅助子函数///
void Edge_Point_initial()//边、顶点数据初始化
{
int i;
for (i=0;i<POINT_NUM;i++)plib[i]=i;//顶点序号赋初值elib[0].from=0;
elib[0].to=1;
elib[0].w=1;//第0条边数据elib[1].from=0;
elib[1].to=2;
elib[1].w=1;//第1条边数据elib[2].from=1;
elib[2].to=2;
elib[2].w=1;//第2条边数据elib[3].from=1;
elib[3].to=4;
elib[3].w=1;//第3条边数据elib[4].from=1;
elib[4].to=3;
elib[4].w=1;//第4条边数据elib[5].from=2;
elib[5].to=5;
elib[5].w=1;//第5条边数据elib[6].from=2;
elib[6].to=4;
elib[6].w=1;//第6条边数据}void lebset() //顶点覆盖标志数组置1
{
int i;
for (i=0;i<POINT_NUM;i++)leb[i]=1;}int lebtest()//顶点覆盖标志数组累加测试
{
int i,j;
for (i=0,j=0;i<POINT_NUM;i++)j+=leb[i];
if (j==0) return 0;
else return 1;}int fugaitest(vectorE E)//测试解对象是否为可行解,即是否为覆盖,返回值:1000,非覆盖;其它,覆盖数
{
int i,j,sum;
lebset();顶点覆盖标志数组置1
for (i=0,sum=0;i<EDGE_NUM;i++)
{
if (E.e[i]==1)//如果该边被选中,则其顶点标志置0
{sum+=1;leb[elib[i].from]=0;leb[elib[i].to]=0;
}
}
j=lebtest();
lebset();顶点覆盖标志数组置1
if (j==0) return sum;
else return 1000;
}N_TABE* N_tableCreate( )//邻域辅助索引链表构造
{
int kmax=(1<<EDGE_NUM)-1;
int i,j,n,t;
int a[EDGE_NUM];
N_TABE*top=NULL,* p=NULL,*q=NULL;for (n=1;n<=kmax;n++)
{for (i=0;i<EDGE_NUM;i++)a[i]=0;for (i=0,t=0,j=n;i<EDGE_NUM;i++){a[EDGE_NUM-i-1]=j%2;t+=a[EDGE_NUM-i-1];j=j>>1;}if ((t>=1)&&(t<=N_K))//{q=new N_TABE;q->next=NULL;q->ve=a;if (top==NULL){top=q;p=q;}else{p->next=q;p=q;}}}
return top;}//主控制函数//
void main ( )
{Edge_Point_initial();//边、顶点数据初始化
H_clear();//禁忌队列初始化,队列为空
int e0[]={1,1,1,1,1,1,1};
vectorE E0=e0;//并初始化解对象
vectorE Et;
vectorE Ebest=E0;//最优解赋初值
vectorE Enow=E0;//当前覆盖
int F_min=fugaitest(E0);//最小覆盖数赋初值
int F_now=F_min;//最小覆盖数赋初值
int i,j,step,k,t;N_TABE *N_head=N_tableCreate( );//邻域辅助索引表构造
N_TABE  *p=N_head;//工作指针vectorE Enowbest,Enowbest0;//当前跌代最优解
int F_nowmin=fugaitest(Enowbest);//当前跌代最小覆盖数赋初值
int enow[]={0,0,0,0,0,0,0};//当前跌代后选解最优解初值
H_add( Enow);//禁忌表队列赋初值cout<<"当前最优解:";for (i=0;i<EDGE_NUM;i++)   {if (Enow.e[i]==1){ cout<<"("<<elib[i].from<<","<<elib[i].to<<"),";}else{cout<<"(-,-),";}} cout<<"--,";cout<<"当前最小覆盖数:"<<F_min<<endl;for (step=0;step<stepMAX;step++)
{Enowbest=enow;Enowbest0=Enowbest;//用于比较初值是否变化F_nowmin=fugaitest(Enowbest);//当前跌代最小覆盖数赋初值//当前跌代最小覆盖数赋初值
//
p=N_head;
while(p->next!=NULL)//遍历K-邻域所有邻居
{Et=Enow-p->ve;//当前边选择组合,满足K条边距离要求,但还未证实为覆盖p=p->next;//立即更新p指针t=fugaitest(Et);//覆盖数if (t==1000) //不满足覆盖要求,Et不是E0 K-邻居{continue;}else //满足覆盖要求,Et是E0 K-邻居{if (H_IsNot(Et)==-1)//最优且不在禁忌表中{if (Enowbest==Enowbest0){Enowbest=Et;F_nowmin=t;}else{if (t<F_nowmin){Enowbest=Et;F_nowmin=t;cout<<"当前最优解:";for (i=0;i<EDGE_NUM;i++){if (Enowbest.e[i]==1){ cout<<"("<<elib[i].from<<","<<elib[i].to<<"),";}else{cout<<"(-,-),";}}cout<<"--,";cout<<"当前最小覆盖数:"<<F_nowmin<<endl;}}}}}if (Enowbest==Enowbest0)//无侯选解,特赦//
{p=N_head;while(p->next!=NULL)//遍历K-邻域所有邻居{Et=Enow-p->ve;//当前边选择组合,满足K条边距离要求,但还未证实为覆盖p=p->next;//立即更新p指针t=fugaitest(Et);if (t==1000) //不满足覆盖要求,Et不是E0 K-邻居{continue;}else //满足覆盖要求,Et是E0 K-邻居{if (Enowbest==Enowbest0){Enowbest=Et;F_nowmin=t;}else{if (t<F_nowmin){Enowbest=Et;F_nowmin=t;}}}  }if (Enowbest==Enowbest0){break;}else//如果在禁忌表中有当前次跌代,特赦当前次跌代的解向量{t= H_IsNot(Enowbest);H_free(t);Enow=Enowbest;//更新当前解}}
else {if (F_nowmin<F_min){Ebest=Enowbest;F_min=F_nowmin;//记忆最优解}Enow=Enowbest;//更新当前解if ((H_s==1)&&(H_front==H_rear))H_delete( );//如果队列满,清除排头H_add( Enow);//更新禁忌表}}//迭代循环cout<<endl<<"全局最优解:";
for (i=0;i<EDGE_NUM;i++)
{
if (Ebest.e[i]==1)
{
cout<<"("<<elib[i].from<<","<<elib[i].to<<"),";
}}
cout<<"--,";
cout<<"全局最小覆盖数:"<<F_min<<endl;delete [] N_head;}

(二)赋权边覆盖:

#include "stdafx.h"#include<iostream>
using namespace std;/控制参数
#define EDGE_NUM  7 //边数量
#define POINT_NUM 6 //顶点数量
#define N_K 2 //K邻域
#define HNUM  4    //禁忌队列长度,队列元素为一可行解对象static  int stepMAX=50;//最大迭代次数,终止条件
static  float GOAL=100;//最优目标值 /主要数据结构定义/
struct EDGE
{
float w;//边的权值
int from;//边起始顶点序号
int to;//边终止顶点序号};//边结构体数据类型static EDGE elib[EDGE_NUM ];//边数据存储数组
static int plib[POINT_NUM];//顶点序号数据存储数组
static int leb[POINT_NUM ];//顶点覆盖标志数组class vectorE
{
public:int e[EDGE_NUM];//解向量中各边是否被选种标志 int i,j;vectorE(int a[]){for (i=0;i<EDGE_NUM;i++)e[i]=a[i];}vectorE(){for (i=0;i<EDGE_NUM;i++)e[i]=-1;//默认参数下,解向量是非法的标志-1}vectorE(vectorE & VE){for (i=0;i<EDGE_NUM;i++)e[i]=VE.e[i];}int operator==(vectorE VE)//运算符重载{for (i=0,j=0;i<EDGE_NUM;i++){if (e[i]!=VE.e[i])break; else j+=1;}if(j==EDGE_NUM)return 1;else return 0;}void operator=(vectorE VE)//运算符重载{for (i=0;i<EDGE_NUM;i++)e[i]=VE.e[i];}void operator=(int a[])//运算符重载{for (i=0;i<EDGE_NUM;i++)e[i]=a[i];}
vectorE operator-(vectorE VE)运算符重载,返回邻居
{vectorE et=e;for (i=0;i<EDGE_NUM;i++){if (VE.e[i]==1)et.e[i]=1-e[i]; }
return et;
}float WE()
{
float wt=0.0;
for (i=0;i<EDGE_NUM;i++)
{  wt+=double(e[i])*elib[i].w;
}
return wt>0?wt:-wt;
}
};//可行解类static vectorE H[HNUM];//禁忌队列
static H_rear=HNUM;//禁忌队列对尾指针
static H_front=HNUM;//禁忌队列对头指针
static H_s=0;//禁忌队列满标志struct N_TABE//邻域索引表结构
{vectorE ve;struct N_TABE * next;
};///禁忌队列操作函数
void H_clear()//禁忌队列初始化
{
vectorE ve;//非法解
int i;
for (i=0;i<HNUM;i++)H[i]=ve;//初始化队列元素,
H_rear=HNUM;//禁忌队列对尾指针
H_front=HNUM;//禁忌队列对头指针
H_s=0;//禁忌队列满标志
}bool H_add( vectorE ve)//入队运算
{if ((H_s==1)&&(H_front==H_rear)){cout<<"队列已满,无法插入!"<<endl;return false;}
H_rear+=1;
if (H_rear==HNUM+1)H_rear=1;
H[H_rear-1]=ve;
H_s=1;//禁忌队列满标志
return true;
}bool H_delete( vectorE & ve)//出队运算,有参数
{vectorE ve_t;//非法解if ((H_s==0)&&(H_front==H_rear)){cout<<"队列已空,无法删除!"<<endl;return false;}
H_front+=1;
if (H_front==HNUM+1)H_front=1;
ve=H[H_front-1];
H[H_front-1]=ve_t;if (H_front==H_rear)H_s=0;
return true;
}bool H_delete( )//出队运算重载,无参数
{vectorE ve_t;//非法解if ((H_s==0)&&(H_front==H_rear)){cout<<"队列已空,无法删除!"<<endl;return false;}
H_front+=1;
if (H_front==HNUM+1)H_front=1;
//ve=H[H_front-1];
H[H_front-1]=ve_t;
if (H_front==H_rear)H_s=0;
return true;
}int H_IsNot(vectorE ve)//测试解对象ve是否在禁忌队列中,若在,返回在队列中的序号,如不在,返回-1
{int i=H_front+1;if (i==HNUM+1)i=1;if ((H_s==0)&&(H_front==H_rear))return -1;else if (i>H_rear){for (;i<=HNUM;i++){if (H[i-1]==ve) return i;}for (i=1;i<=H_rear;i++){if (H[i-1]==ve) return i;}}else{for (;i<=H_rear;i++){if (H[i-1]==ve) return i;}}return -1;
}void H_free(int n)//特赦禁忌队列中序号为n的元素
{
int i;
vectorE ve_t;//非法解
if ((n<0)||(n>HNUM))
{   cout<<"序号非法,不存在特赦元素!"<<endl;return;
}if ((H_s==0)&&(H_front==H_rear)){cout<<"队列为空,不存在特赦元素!"<<endl;return;}if( ((H_front+1)% HNUM)==n) //如果特赦元素为排头元素{H_front+=1;if (H_front==HNUM+1)H_front=1;
//ve=H[H_front-1];H[H_front-1]=ve_t;if (H_front==H_rear)H_s=0;}//如果特赦元素为排头元素else if( H_rear==n) //如果特赦元素为对尾元素{H[H_rear-1]=ve_t;H_rear-=1;if (H_rear==0)H_rear=HNUM;if (H_front==H_rear)H_s=0;}//如果特赦元素为排头元素else{if (n>H_rear){for (i=n;i<=HNUM-1;i++) {H[i-1]=H[i];}H[HNUM-1]=H[0];for (i=1;i<H_rear-1;i++){H[i-1]=H[i];}H_rear-=1;if (H_rear==0)H_rear=HNUM;}else{for (i=n;i<=H_rear-1;i++) {H[i-1]=H[i];}H_rear-=1;if (H_rear==0)H_rear=HNUM;}}
}void H_display()//禁忌对队列显示,用于调试程序
{int i,j,a,b;if ((H_s==0)&&(H_front==H_rear)){cout<<"队列为空,无法显示!"<<endl;return ;}else{a=H_front+1;if (a==HNUM+1)a=1;b=H_rear;if (a>b){for (i=a;i<=HNUM;i++){for(j=0;j<EDGE_NUM;j++)cout<<H[i-1].e[j]<<",";cout<<endl;}
for (i=1;i<=H_rear;i++){for(j=0;j<EDGE_NUM;j++)cout<<H[i-1].e[j]<<",";cout<<endl;}}else{for (i=a;i<=b;i++){for(j=0;j<EDGE_NUM;j++)cout<<H[i-1].e[j]<<",";cout<<endl;}}cout<<"H_front,H_rear,H_s are:"<<H_front<<","<<H_rear<<","<<H_s<<endl;}}/辅助子函数///
void Edge_Point_initial()//边、顶点数据初始化
{
int i;
for (i=0;i<POINT_NUM;i++)plib[i]=i;//顶点序号赋初值elib[0].from=0;
elib[0].to=1;
elib[0].w=0.2;//第0条边数据elib[1].from=0;
elib[1].to=2;
elib[1].w=1.3;//第1条边数据elib[2].from=1;
elib[2].to=2;
elib[2].w=2.4;//第2条边数据elib[3].from=1;
elib[3].to=4;
elib[3].w=2;//第3条边数据elib[4].from=1;
elib[4].to=3;
elib[4].w=0.1;//第4条边数据elib[5].from=2;
elib[5].to=5;
elib[5].w=1;//第5条边数据elib[6].from=2;
elib[6].to=4;
elib[6].w=1.4;//第6条边数据}void lebset() //顶点覆盖标志数组置1
{
int i;
for (i=0;i<POINT_NUM;i++)leb[i]=1;}int lebtest()//顶点覆盖标志数组累加测试
{
int i,j;
for (i=0,j=0;i<POINT_NUM;i++)j+=leb[i];
if (j==0) return 0;
else return 1;}int fugaitest(vectorE E)//测试解对象是否为可行解,即是否为覆盖,返回值:1000,非覆盖;其它,覆盖数
{
int i,j,sum;
lebset();顶点覆盖标志数组置1
for (i=0,sum=0;i<EDGE_NUM;i++)
{
if (E.e[i]==1)//如果该边被选中,则其顶点标志置0
{sum+=1;leb[elib[i].from]=0;leb[elib[i].to]=0;
}
}
j=lebtest();
lebset();顶点覆盖标志数组置1
if (j==0) return sum;
else return 1000;
}N_TABE* N_tableCreate( )//邻域辅助索引链表构造
{
int kmax=(1<<EDGE_NUM)-1;
int i,j,n,t;
int a[EDGE_NUM];
N_TABE*top=NULL,* p=NULL,*q=NULL;for (n=1;n<=kmax;n++)
{for (i=0;i<EDGE_NUM;i++)a[i]=0;for (i=0,t=0,j=n;i<EDGE_NUM;i++){a[EDGE_NUM-i-1]=j%2;t+=a[EDGE_NUM-i-1];j=j>>1;}if ((t>=1)&&(t<=N_K))//{q=new N_TABE;q->next=NULL;q->ve=a;if (top==NULL){top=q;p=q;}else{p->next=q;p=q;}}}
return top;}//主控制函数//
void main ( )
{Edge_Point_initial();//边、顶点数据初始化
H_clear();//禁忌队列初始化,队列为空
int e0[]={1,1,1,1,1,1,1};
vectorE E0=e0;//并初始化解对象
vectorE Et;
vectorE Ebest=E0;//最优解赋权赋初值
vectorE Enow=E0;//当前覆盖
float F_min= Enow.WE();//最小赋权覆盖数赋初值
float F_now=F_min;//最小赋权覆盖数赋初值
int i,j,step,k,t;N_TABE *N_head=N_tableCreate( );//邻域辅助索引表构造
N_TABE  *p=N_head;//工作指针vectorE Enowbest,Enowbest0;//当前跌代最优解
float F_nowmin=Enowbest.WE();//当前跌代最小覆盖数赋初值
int enow[]={0,0,0,0,0,0,0};//当前跌代后选解最优解初值
H_add( Enow);//禁忌表队列赋初值cout<<"当前最优解:";for (i=0;i<EDGE_NUM;i++)   {if (Enow.e[i]==1){ cout<<"("<<elib[i].from<<","<<elib[i].to<<"),";}else{cout<<"(-,-),";}} cout<<"--,";cout<<"当前最小赋权值:"<<F_min <<endl;for (step=0;step<stepMAX;step++)
{Enowbest=enow;Enowbest0=Enowbest;//用于比较初值是否变化F_nowmin=Enowbest.WE();//当前跌代最小覆盖数赋初值//当前跌代最小覆盖数赋初值
//
p=N_head;
while(p->next!=NULL)//遍历K-邻域所有邻居
{Et=Enow-p->ve;//当前边选择组合,满足K条边距离要求,但还未证实为覆盖p=p->next;//立即更新p指针t=fugaitest(Et);//覆盖数if (t==1000) //不满足覆盖要求,Et不是E0 K-邻居{continue;}else //满足覆盖要求,Et是E0 K-邻居{if (H_IsNot(Et)==-1)//最优且不在禁忌表中{if (Enowbest==Enowbest0){Enowbest=Et;F_nowmin=Enowbest.WE();}else{if (Et.WE()<F_nowmin){Enowbest=Et;F_nowmin=Et.WE();cout<<"当前最优解:";for (i=0;i<EDGE_NUM;i++){if (Enowbest.e[i]==1){ cout<<"("<<elib[i].from<<","<<elib[i].to<<"),";}else{cout<<"(-,-),";}}cout<<"--,";cout<<"当前最小赋权值:"<<F_nowmin<<endl;}}}}}if (Enowbest==Enowbest0)//无侯选解,特赦//
{p=N_head;while(p->next!=NULL)//遍历K-邻域所有邻居{Et=Enow-p->ve;//当前边选择组合,满足K条边距离要求,但还未证实为覆盖p=p->next;//立即更新p指针t=fugaitest(Et);if (t==1000) //不满足覆盖要求,Et不是E0 K-邻居{continue;}else //满足覆盖要求,Et是E0 K-邻居{if (Enowbest==Enowbest0){Enowbest=Et;F_nowmin=t;}else{if (Et.WE()<F_nowmin){Enowbest=Et;F_nowmin=Et.WE();}}}  }if (Enowbest==Enowbest0){break;//跌代终止}else//如果在禁忌表中有当前次跌代,特赦当前次跌代的解向量{t= H_IsNot(Enowbest);H_free(t);Enow=Enowbest;//更新当前解}}
else {if (F_nowmin<F_min){Ebest=Enowbest;F_min=F_nowmin;//记忆最优解}Enow=Enowbest;//更新当前解if ((H_s==1)&&(H_front==H_rear))H_delete( );//如果队列满,清除排头H_add( Enow);//更新禁忌表}}//迭代循环cout<<endl<<"全局最优解:";
for (i=0;i<EDGE_NUM;i++)
{
if (Ebest.e[i]==1)
{
cout<<"("<<elib[i].from<<","<<elib[i].to<<"),";
}}
cout<<"--,";
cout<<"全局最小赋权值:"<<F_min<<endl;delete [] N_head;}

赋权边覆盖问题——采用禁忌搜索算法的C++实现相关推荐

  1. 禁忌搜索算法(TABU)解决路线规划问题(CVRP)

    文章目录 禁忌搜索算法解决路线规划问题 问题定义 CVRP问题解决算法 禁忌搜索算法 局部搜索的两种策略 局部搜索的缺点 禁忌搜索算法的提出 禁忌搜索算法流程图 禁忌搜索算法伪码 算法结果 统计结果 ...

  2. 【算法】禁忌搜索算法(Tabu Search,TS)超详细通俗解析附C++代码实例

    01 什么是禁忌搜索算法? 1.1 先从爬山算法说起 爬山算法从当前的节点开始,和周围的邻居节点的值进行比较. 如果当前节点是最大的,那么返回当前节点,作为最大值 (既山峰最高点):反之就用最高的邻居 ...

  3. 组合赋权法之python

    目录 1.简介 2.算法原理 2.1 指标正向化 2.2 数据标准化 2.3 计算主观权重 2.4 计算客观权重 2.5 计算组合权重 2.6 计算的得分 3.实例分析 3.1 读取数据 3.2 指标 ...

  4. 组合赋权法之matlab

    目录 1.简介 2.算法原理 2.1 指标正向化 2.2 数据标准化 2.3 计算主观权重 2.4 计算客观权重 2.5 计算组合权重 2.6 计算的得分 3.实例分析 3.1 读取数据 3.2 指标 ...

  5. 基于禁忌搜索算法的三维装箱问题

    装箱问题 装箱问题是复杂的离散组合最优化问题.所谓组合优化,是指在离散的.有限的数学结构上,寻找一个满足给定条件,并使其目标函数值达到最大或最小的解.经典的装箱问题要求把一定数量的物品放入容量相同的一 ...

  6. 基于禁忌搜索算法的TSP问题求解matlab仿真

    目录 1.算法概述 2.仿真效果 3.matlab仿真源码 1.算法概述 禁忌搜索(Tabu Search,TS)算法是组合优化算法的一种,是局部搜索算法的扩展.禁忌搜索算法是人工智能在组合优化算法中 ...

  7. 【优化布局】matlab基于禁忌搜索算法求解基站选址问题代码

    1 简介 物流配送中心选址问题在物流网络规划中占有非常重要的地位,选址的合理与否直接关系到配送中心未来的发展.针对企业选址的一般要求,以配送中心总成本最小为目标,构造了一种物流配送中心选址模型.该模型 ...

  8. 禁忌搜索算法求解TSP旅行商问题Matlab实现

    一. 禁忌搜索算法 禁忌搜索算法是一种全局性邻域搜索算法,模拟人类具有记忆功能的寻优特征.它通过局部邻域搜索机制和相应的禁忌准则来避免迂回搜索,并通过破禁水平来释放一些被禁忌的优良状态,进而保证多样化 ...

  9. 【优化规划】基于matlab禁忌搜索算法求解配电网无功补偿优化规划问题【含Matlab源码 1842期】

    一.基于禁忌搜索算法的无功优化参数选择及流程 禁忌搜索方法是Glover F在1986年首次提出的一种智能启发式算法.鉴于禁忌搜索算法是对局部邻域搜索的一种扩展,通过引入一个灵活的存储结构和相应的禁忌 ...

最新文章

  1. 030_jdbc-mysql事务
  2. Centos(阿里云) 安装python3.4以及pip3
  3. Intellij Idea导出可执行的jar包
  4. 聊天机器人突然火了,能解决那方面的需求吗?
  5. 如何使用vue组件搭建网页并打包发布
  6. JavaScript执行bat文件清理浏览器缓存
  7. ~~队列(数据结构)(附模板题 AcWing 829. 模拟队列)
  8. ant design pro模板_ant design pro 当中改变ant design 组件的样式和 数据管理
  9. 日常工作中,个人总结的 - Git - 常用操作方法 (三)
  10. python生成excel模板_使用python创建excel表格 --- XlsxWriter模板详解
  11. 查看.pth文件里面保存了哪些权重及那些权重的shape
  12. JAVA 使用SSH/springboot集成 CXF框架发布Webservice
  13. 小猪短租住房信息爬取
  14. 950个织梦网dede模板源码
  15. php 插件推荐,Typecho实用插件推荐(一)
  16. Java解决上台阶问题
  17. TransactionScope使用(二)——msdtc不可用
  18. PEP8风格是什么?
  19. Unity 颜色查找表富文本颜色
  20. java飞鸽源码_java版本的飞鸽编写(一)

热门文章

  1. DELPHI 线程类
  2. html z-index不显示,CSS3关于z-index不生效问题的解决
  3. 【c++中内存拷贝函数(C++ memcpy)详解】
  4. mysql查询姓张的同学_Mysql 基础2 (sql查询语句)
  5. WordPress优化教程大全
  6. echarts自定义区域地图
  7. 9.0 OTA升级logo不更新,输入法不更新
  8. 新年开工第一篇文章——推荐几个值得中小企业使用的ARM9/ARM11/Cortex A8处理器
  9. SpringCloud学习笔记(十二)基于Hystrix解决雪崩效应
  10. 二叉树的非递归遍历详解