赋权边覆盖问题是图论中的经典问题。
本文详细讨论了禁忌搜索算法求解赋权边覆盖问题的定义、原理及求解思路,在文末给出了实验结果及完整的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; }