回溯法很简单,但是时间太长了,我在程序中使用了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级的计时器,这也太无聊了
不如直接看一下表,以小时为单位得了
完整的程序在这儿下载
程序写的比较乱
欢迎批评、建议和讨论
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;
}