動的計画法を用いて旅行者問題(TSP)を解くC言語実現(一)

4513 ワード


あるセールスマンは都市v 1から出発し、他の都市v 2,v 3,...,v 6を1回ずつ1回だけ訪問し、最後にv 1に戻る.Dは各都市間の距離行列である.
質問:このセールスマンはどのようにルートを選択して、総行程を最も短くすることができますか?
D=   0 10 20 30 40 50
12 0 18 30 25 21
23 19 0   5 10 15
34 32   4   0   8 16
45 27 11 10   0 18
56 22 16 20 12 0
問題分析:n個の都市を1,2,...,n.与えられた集合Sに対して{2,3,4,...n}と要素kがSに属し、C(S,k)は都市1から出発し、Sの中で各都市をちょうど1回遍歴し、最後に都市kでの最適費用を終了する.
すると、Sに1つの要素kしかない場合、C(S,k)=D[1][k];
Sに複数の要素がある場合、C(S,k)=
この方程式の解は、所与の大きさの全ての集合S及びS中の可能な各要素kに対して、C(S,k)の値を計算することを要求する.
Sが{2,3,4,...n}に等しい場合、C(S,k)の値がSに属する任意の要素kに対して計算によって得られた場合、最適なループの最も費用は
アルゴリズム複雑度解析:計算に必要な加算と比較の回数はO(n^2*2^n)に等しい
空間複雑度:O(n*2^n)
アルゴリズムの改善:集合操作を改善することによって比較回数を低減し、バイナリを利用して集合を表す.集合Sにおける元素kの比較回数が1であるか否かを決定し、時間的複雑度をO(n 2^n)に低減する
 
#include 
#include 
#include 
#include 
#include 
#define MAX_N 10

int mypow(int x, int y)
{
return (int)pow((double)x,(double)y);
}

struct path
{
int current;
int cost;
long set;//2 bits for vector
//struct path *lastNode;
struct path *lastNode;
struct path *next;
};
struct path *D[MAX_N];

/*                 ,    2       
*    n      ,  n    1 n  ,              。
*   k  1  ,  k        ,   0         。
*/
/*       i     set 。
*        ,     set 
*  1    ,  0     
*/
int inSet(int i, int set)
{
if((mypow(2,i-1)&set)>0)
   return 1;
else
   return 0;
}
/*      set     i
* set  i    1,  i     set 
*/
int insertSet(int i,int set)
{
if(inSet(i,set)==0)
   return set|mypow(2,i-1);
return set;
}
/*      set     i
* set  i    0,   set    
*/
int deleteSet(int i, int set)
{
if(inSet(i,set))
{
   set = ~(mypow(2,i-1))&set;
}
return set;
}
/*         
*/
print_path(struct path *p)
{
if(p==NULL)
{
   printf("1");
   return;
}
print_path(p->lastNode);
printf("->%d",p->current+1);
}
/*
*  :              
*  :
*1, n    1,2,…,n.        S  {2,3,...n} k  S。
*2, C(S,k)    1  ,  S         ,       k     .
*3, S       k ,C(S,k)= d(1,k)
*  S         ,C(S,k)        S-k     m,C(s-k,m)+d(m,k)      ,
*4,                   S S         k,   C(S,k)  
*5, S  {2,3,...n} ,  C(S,k)   k  S         ,           
    C(S,k)+d(k,1)      。
*PS:C(S,k) struct path     set = S, current = K, cost = C(S,K)
*/
int tsp(int n, int (*a)[MAX_N])
{
int i,j;
struct path *temp,*p;
struct path **address;
long set;
int cost;
long mincost;
struct path *lastNode;
D[1] = NULL;
// S       k ,C(S,k)= d(1,k)
for(i=1;icurrent = i;
   temp->cost = a[0][i];
   temp->lastNode = NULL;
   temp->next = D[1];
   temp->set = mypow(2,i-1);
   D[1] = temp;
}
//  n-2 ,        J      
for(j=2;jset   
     //               i p->set       。
     //             
     if(inSet(i,p->set)==0)
     {
      // S         ,C(S,k)        S-k     m,C(s-k,m)+d(m,k)      ,
      set = insertSet(i,p->set);
      //  C(S,k)       
      //     ,  cost ,   
      //     ,        struct path  C(S,k)   
      if(address[set]!=NULL&&address[set]->current==i)
      {
       cost = p->cost + a[p->current][i];
       if(cost< address[set]->cost)
       {
        address[set]->cost = cost;
        address[set]->lastNode = p;
       }
      }
      else
      {
       temp = malloc(sizeof(struct path));
       temp->current = i;
       temp->cost = p->cost + a[p->current][i];
       temp->set = set;
       temp->lastNode = p;
       temp->next = D[j];
       D[j] = temp;
       address[set]=temp;
      }
     
     }
     p = p->next;
    }
    free(address);
   }
}
//                   S S         k,   C(S,k)  
// S  {2,3,...n} ,  C(S,k)   k  S         ,           
//C(S,k)+d(k,1)      。
mincost = -1;
p = D[n-1];
while(p)
{
   if(mincost==-1 || mincost > p->cost + a[p->current][0])
   {
    mincost = p->cost + a[p->current][0];
    lastNode = p;
   }
   p = p->next;
}
//      
printf("mincost=%d
",mincost); // print_path(lastNode); printf("->1
"); return mincost; } int main(int argc, char *argv[]) { int a[MAX_N][MAX_N]= { { 0, 10, 20, 30, 40, 50}, {12, 0, 18, 30, 25, 21}, {23, 19, 0, 5, 10, 15}, {34, 32, 4, 0, 8, 16}, {45, 27, 11, 10, 0, 18}, {56, 22, 16, 20, 12, 0} }; int n = 6; tsp(n,a); return EXIT_SUCCESS; }