TSP问题之回溯法 cpp实现

回溯法很简单,但是时间太长了,我在程序中使用了tsplib的ulysses16,十六个城市

目前找到的最优解为

best current: 59.9963
0 14 12 10 8 9 13 4 5 6 11 15 1 2 3 7

比给出的参考标准要好不少

但是比标准数据更好的情况几乎不可能发生

也许是我求距离错了,因为这个case中有负的坐标值,看看再说吧

 

standard path:
0 13 12 11 6 5 14 4 10 8 9 15 2 1 3 7
length of standard path:
 79.6844

 

找到这个解后一个多小时内没有更优解

我实在没有耐心运行下去了

于是想保存运行参数,在下次运行时载入参数继续运行

在写了之后,却发现行不通,程序使用了递归调用,要保存参数,就要保存所有深度的参数,而我只保存了最后一层

要真正实现这个功能,就得用较大篇幅写保存参数了

我没去写

 

如果哪位仁兄完整运行了本程序,劳驾把最优解贴上来

 

程序中居然使用了ms级的计时器,这也太无聊了

不如直接看一下表,以小时为单位得了

 

完整的程序在这儿下载

 

程序写的比较乱

欢迎批评、建议和讨论

 

/* * backtracking solution for TSP * * @author:onezeros@yahoo.cn */ #include <iostream> #include <fstream> #include <algorithm> #include <vector> #include <stdlib.h> #include <time.h> #include <assert.h> using namespace std; //fast sorting,descending int quicksort_partion(vector<int>&queueNext,int i,int j,const vector<vector<double> >& distance,int currPos) { int tmp=queueNext[i]; double tmp_d=distance[currPos][tmp]; int h=i; for (int k=i+1;k<=j;k++) { double k_d=distance[currPos][k]; if (k_d>tmp_d) { h++; int t=queueNext[h]; queueNext[h]=queueNext[k]; queueNext[k]=t; } } int t=queueNext[i]; queueNext[i]=queueNext[h]; queueNext[h]=t; return h; } void quicksort(vector<int>&queueNext,int i,int j,const vector<vector<double> >& distance,int currPos) { if (i<j) { int p=quicksort_partion(queueNext,i,j,distance,currPos); quicksort(queueNext,i,p-1,distance,currPos); quicksort(queueNext,p+1,j,distance,currPos); } } // params: // bestPath: length of best path found for the moment // currPathLen:length of partial path from start city to currentPos // queueNext: a queue of avalible cities to go // currentPos: current Position // distance: distance table // path: the path from start city to currentPos void backtrack(double&bestPath,double currPathLen,vector<int> queueNext, int currentPos,const vector<vector<double> >& distance, vector<int>&path) { path.push_back(currentPos); /*cout<<“current Position: “<<currentPos<<endl; for (int i=0;i<queueNext.size();i++){ cout<<queueNext[i]<<” “; } cout<<endl;*/ if (queueNext.size()==0){//leaf nods for (int i=0;i<path.size()-1;i++){ cout<<path[i]<<” “; } cout<<endl; currPathLen+=distance[currentPos][0]; if (currPathLen<bestPath){ bestPath=currPathLen; cout<<bestPath<<endl; //output to a file fstream f(“data/result.txt”,ios::app); f<<“best current: “<<bestPath<<endl; for (int i=0;i<path.size();i++){ f<<path[i]<<” “; } f<<endl; f.close(); } }else{ //sort queueNext by distance between element in queneNext and currentPos //the last one in queue is nearest to currPos quicksort(queueNext,0,queueNext.size()-1,distance,currentPos); for (int i=queueNext.size()-1;i>=0;i–){ //copy all elements except the last one to next generation vector<int> next_queue(queueNext.begin(),queueNext.end()); next_queue.erase(next_queue.begin()+i); //update current length double next_currLen=currPathLen+distance[currentPos][queueNext[i]]; if (next_currLen<bestPath){//limitation backtrack(bestPath,next_currLen,next_queue,queueNext[i],distance,path); } } } path.pop_back(); } int main() { srand((unsigned)time(NULL)); //read data from file //because backtracking will take much time ,so I use a smaller data set here. fstream filein(“data/ulysses16.tsp.processed”,ios::in); if (filein==NULL){ cout<<“cannot open data file”<<endl; return 1; } //number of cities unsigned int cityNum; //read data from filein filein>>cityNum; //standard path int* standardPath; standardPath=new int[cityNum]; for (int i=0;i<cityNum;i++){ filein>>standardPath[i]; } //distance between cities vector<vector<double> > distance; for (int i=0;i<cityNum;i++){ vector<double> v; for (int j=0;j<cityNum;j++){ double d; filein>>d; v.push_back(d); } distance.push_back(v); } //write fileout fstream fileout(“data/result.txt”,ios::out); if (fileout==NULL){ cout<<“cannot open a file to write data”<<endl; return 1; } fileout<<“standard path:”<<endl; double standardbestlen=0; for (int i=0;i<cityNum;i++){ fileout<<standardPath[i]<<” “; } for (int i=0;i<cityNum-1;i++){ standardbestlen+=distance[standardPath[i]][standardPath[i+1]]; } standardbestlen+=distance[standardPath[cityNum-1]][standardPath[0]]; fileout<<endl<<“length of standard path: “<<endl<<” “<<standardbestlen<<endl; cout<<“length of standard path: “<<endl<<” “<<standardbestlen<<endl; //assume start from city 0 vector<int> queueNext; for (int i=1;i<cityNum;i++){ queueNext.push_back(i); } //length of best path found double best_path_len=1<<(8*sizeof(int)-2); vector<int> path; double currentPathLen=0; int currentPos=0; //timer time_t start,finish; start=clock(); backtrack(best_path_len,currentPathLen,queueNext,currentPos,distance,path); finish=clock(); cout<<“time used :”<<finish-start<<” ms”<<endl; fileout<<“length of best Path found:”<<endl <<best_path_len<<endl <<“time used :”<<finish-start<<” ms”<<endl; //free memory///////////////////////////////////////////////////////////// filein.close(); fileout.close(); delete[] standardPath; return 0; }

    原文作者:回溯法
    原文地址: https://blog.csdn.net/onezeros/article/details/5594477
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞