算法-动态规划2-TSP问题
问题:
旅行家要旅行n个城市,要求各个城市经历且仅经历一次然后回到出发城市,并要求所走的路程最短。
设s, s1, s2, …, sp, s是从s出发的一条路径长度最短的简单回路,假设从s到下一个城市s1已经求出,则问题转化为求从s1到s的最短路径,显然s1, s2, …, sp, s一定构成一条从s1到s的最短路径,所以TSP问题是构成最优子结构性质的,用动态规划来求解也是合理的。
代码:
#include <iostream>
#include <stdio.h>
#include<iomanip>
using namespace std;
int dis[12][12], d[12][1 << 11];//距离地图表,d函数表,d[]为动态规划存储的城市经过矩阵
int main()
{
int n, temp, minDis;
//给距离地图表赋值
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf_s("%d", &dis[i][j]);
}
}
//给d函数表赋值
for (int i = 1; i < n; i++) { //将所有城市到第0个城市的路径初始化为两市间的距离
d[i][0] = dis[i][0];
}
//除了第0行以外的其余
for (int j = 1; j < (1 << (n - 1)); j++) {//j用二进制表示的城市集合,先说j再说i,动态规划从j的底层到上层,j数值越来越大
for (int i = 1; i < n; i++) {
//i不在j表示的城市集合中,可以对d[i][j]赋值,否则赋0;
if (((1 << (i - 1)) & j) == 0) {
//temp=dis[i][k]+d[k][V-{k}]开始对V中所有的k进行遍历
int minDis = 60000;
for (int k = 1; k < n; k++) {
if ((1 << (k - 1)) & j) {//k表示的城市在j表示的城市集合中
temp = dis[i][k] + d[k][j - (1 << (k - 1))];
if (temp < minDis) {//d(1,{2,3})=min{ C12+d(2,{3})||C13+d(3,{2})}
minDis = temp; //所有k中最小的距离
d[i][j] = minDis;//给d函数表每个位置赋值
}
}
}
}
}
}
//对第0行最后一个d(0,{123})赋值,d(0,{1,2,3})=min {C01+d(1,{2,3})|| C02+d{2,{1,3}}||C03+d{3,{1,2}})
minDis = 600;
for (int k = 1; k < n; k++) {
temp = dis[0][k] + d[k][((1 << (n - 1)) - 1) - (1 << (k - 1))];//d[k][{123}-{k}]
if (minDis > temp) {
minDis = temp;
d[0][(1 << (n - 1)) - 1] = minDis;
}
}
//此部分可以输出看看形成的d[][]矩阵,便于理解执行过程
for (int i = 0; i < n; i++) {
for (int j = 0; j < (1 << (n - 1)); j++) {
cout << d[i][j] << " ";
}
cout << endl;
}
/*cout << d[0][(1 << (n - 1)) - 1];*/
return 0;
}