【问题标题】:TSP using Dynamic Programming [closed]使用动态编程的 TSP [关闭]
【发布时间】:2014-12-26 06:36:45
【问题描述】:

我正在学习 TSP,发现了这个 TSP 的递归解决方案

int compute(int start,int set)
{   int masked,mask,result=INT_MAX,temp,i;//result stores the minimum 
    if(g[start][set]!=-1)//memoization DP top-down,check for repeated subproblem
        return g[start][set];
    for(i=0;i<n;i++)
        {   //npow-1 because we always exclude "home" vertex from our set
            mask=(npow-1)-(1<<i);//remove ith vertex from this set
            masked=set&mask;
            if(masked!=set)//in case same set is generated(because ith vertex was not present in the set hence we get the same set on removal) eg 12&13=12
            {   
                temp=adj[start][i]+compute(i,masked);//compute the removed set
                if(temp<result)
                    result=temp,p[start][set]=i;//removing ith vertex gave us minimum
            }
        }
        return g[start][set]=result;//return minimum
}

我不明白屏蔽是如何工作的,如何在不使用递归的情况下将其更改为动态编程解决方案,请帮助我。

【问题讨论】:

  • 这已经是自上而下的动态规划方案了,要改成自下而上的形式吗?
  • @PhamTrung 你能解释一下吗!!!请
  • 嗯,有什么不明白的?动态规划还是位掩码?
  • mask=(npow-1)-(1&lt;&lt;i) , ` masked=set&mask;` if(masked!=set) 为什么这些行
  • 如何让它不递归,请帮忙

标签: c++ algorithm traveling-salesman


【解决方案1】:

Here 是一个传统的 TSP 问题,这里是它的解决方案。我想这可能对你有帮助。

int map[15][15];
int dp[(1<<12)+5][12];

int main() {
    int i,j,n,ans,k,p;
    while(1) {
        scanf("%d",&n);
        if (n==0) break;
        n++;
        for (i=0; i<n; i++) {
            for (j=0; j<n; j++) {
                scanf("%d",&map[i][j]);
            }
        }
        //floyd algorithm, get any two points's minimum distance
        for (k=0; k<n; k++) {
            for (i=0; i<n; i++) {
                for (j=0; j<n; j++) {
                    if (i!=j && i!=k && j!=k) map[i][j]=min(map[i][k]+map[k][j],map[i][j]);
                }
            }
        }
        memset(dp,-1,sizeof(dp));
        dp[1][0]=0;
        // TSP solution here,bitmask and DP
        for (i=1; i<(1<<n); i++) {// the current state
            for (j=0; j<n; j++) {// during the current state,the last station is j
                if (dp[i][j]==-1) continue;
                for (k=1; k<n; k++) {//the next state is k
                    if ((i & (1<<k))!=0) continue;
                    p=(i | (1<<k));// the new state(join k)
                    if (dp[p][k]==-1) dp[p][k]=dp[i][j]+map[j][k];
                    dp[p][k]=min(dp[p][k],dp[i][j]+map[j][k]);
                }
            }
        }
        ans=INF;
        // get answer
        for (i=1; i<n; i++) {
            if (dp[(1<<n)-1][i]>0) ans=min(ans,dp[(1<<n)-1][i]+map[i][0]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

【讨论】:

  • 感谢您,如果我发现问题会通知您!!!!
  • if (dp[(1&lt;&lt;n)-1][i]&gt;0) 为什么一点可能永远不是终点
  • 因为可能有一个或多个点我无法访问,即该点与其他点断开连接。例如,点 1,2,3,4是强连接但点5远离它们(5和其他点之间没有边),那么在状态11111和5是一个终点,这个状态根本无法到达。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 2021-05-04
  • 2014-10-30
  • 1970-01-01
  • 1970-01-01
  • 2015-07-18
  • 2012-06-15
相关资源
最近更新 更多