# 旅行商问题(travelling salesman problem, TSP) 解题报告

25
20833.3333 17100.0000
20900.0000 17066.6667
21300.0000 13016.6667
21600.0000 14150.0000
21600.0000 14966.6667
21600.0000 16500.0000
22183.3333 13133.3333
22583.3333 14300.0000
22683.3333 12716.6667
23616.6667 15866.6667
23700.0000 15933.3333
23883.3333 14533.3333
24166.6667 13250.0000
25149.1667 12365.8333
26133.3333 14500.0000
26150.0000 10550.0000
26283.3333 12766.6667
26433.3333 13433.3333
26550.0000 13850.0000
26733.3333 11683.3333
27026.1111 13051.9444
27096.1111 13415.8333
27153.6111 13203.3333
27166.6667 9833.3333
27233.3333 10450.0000

#include <iostream>
#include <cassert>
#include <climits>
#include <vector>
#include <queue>
#include <ctime>
using namespace std;

const int N = 25;
int n;
double cities[N][2];
double dis[N][N];
double minedge[N];

struct TSPNode{
vector<int> path;
double plen;
double bnd;

TSPNode()
{
plen = 0;
bnd = -1;
}

double pathlen()
{
return plen;
}

int size()
{
return path.size();
}

int lastcity()
{
if(size() < 1)
{
fprintf(stdout, "error: path is empty.\n");
return -1;
}
return path[path.size() - 1];
}

{
path.push_back(city);
}

void copypath(const vector<int> &p)
{
path = p;
}

bool contains(int city)
{
for(int i = 0; i < path.size(); ++i)
{
if(path[i] == city)
{
return true;
}
}
return false;
}

double bound()
{
if(bnd >= 0)
{
return bnd;
}
bnd = plen;
bool marked[N];
memset(marked, false, sizeof(marked));

for(int i = 0; i < path.size() - 1; ++i)
{
marked[path[i]] = true;
}

for(int i = 0; i < n; ++i)
{
if(!marked[i])
{
bnd += minedge[i];
}
}

return bnd;
}

bool operator<(TSPNode& other)
{
return bound() < other.bound();
}
};

class CompareTSPNode {
public:
bool operator()(TSPNode& t1, TSPNode& t2)
{
if(t1.bound() - t1.size()> t2.bound() - t2.size())
{
return true;
}
//if(abs(t1.bound() - t2.bound()) < 1 && t1.size() < t2.size())
//{
//return true;
//}
return false;
}
};

int main()
{
FILE *fin = fopen("tsp.txt", "r");
freopen("log.txt", "w", stdout);
fscanf(fin, "%d", &n);
assert(n == N);
for(int i = 0; i < n; ++i)
{
fscanf(fin, "%lf%lf", &cities[i][0], &cities[i][1]);
}
//for(int i = 0; i < n; ++i)
//{
//fprintf(stdout, "%d: (%.4lf, %.4lf)\n", i, cities[i][0], cities[i][1]);
//}
for(int i = 0; i < n; ++i)
{
//dis[i][i] = 0;
for(int j = i + 1; j < n; ++j)
{
dis[i][j] = sqrt((cities[i][0] - cities[j][0]) * (cities[i][0] - cities[j][0])
+ (cities[i][1] - cities[j][1]) * (cities[i][1] - cities[j][1]));
dis[j][i] = dis[i][j];
}
}

int initialpath[] = {0, 1, 5, 10, 9, 11, 14, 18, 17, 21, 22, 20, 19, 24, 23, 15, 16, 13, 12, 8, 6, 2, 7, 3, 4, 0};

double infinity = 0;
for(int i = 0; i < n; ++i)
{
infinity += dis[initialpath[i]][initialpath[i + 1]];
}
fprintf(stdout, "%lf\n", infinity);

for(int i = 0; i < n; ++i)
{
dis[i][i] = infinity;
minedge[i] = infinity;
for(int j = 0; j < n; ++j)
{
if(dis[i][j] < minedge[i])
{
minedge[i] = dis[i][j];
}
}
}

//priority_queue<TSPNode, vector<TSPNode>, CmpTSPNode> pq;
priority_queue<TSPNode, vector<TSPNode>, CompareTSPNode> pq;
//priority_queue<TSPNode> pq;

TSPNode node;
//node.bnd = node.calbound();
pq.push(node);

time_t start;
time(&start);
//cout<<"start: "<<start<<endl;
time_t before = start, now;
double mincost = infinity;
while(!pq.empty())
{
TSPNode node = pq.top();
pq.pop();
if(node.bound() >= mincost)
{
continue;
}

fprintf(stdout, "size: %d, bound: %.4lf\n", node.size(), node.bound());

fprintf(stdout, "path: ");
for(int i = 0; i < node.size(); ++i)
{
fprintf(stdout, "%d,", node.path[i]);
}
fprintf(stdout, "\n");

if(node.size() == n - 1)
{
int remaining;
for(int i = 0; i < n; ++i)
{
if(!node.contains(i))
{
remaining = i;
break;
}
}
double cost = node.plen + dis[node.lastcity()][remaining] + dis[remaining][0];
if(cost < mincost)
{
mincost = cost;
fprintf(stdout, "mincost: %.4lf\n", mincost);

time(&now);
fprintf(stdout, "[%d secs].\n", now - start);
}
continue;
}
for(int i = 0; i < n; ++i)
{
if(!node.contains(i))
{
TSPNode newn;
newn.path = node.path;
newn.plen = node.plen + dis[node.lastcity()][i];
//newn.bnd = newn.calbound();
if(newn.bound() < mincost)
{
pq.push(newn);
}
}
}
}
return 0;
}

import java.util.Iterator;
import java.util.List;

public class TSPBranchAndBound {
private int N;
private double mincost;
private List<Integer> tour;
private double[][] dis;

class TSPNode {
Digraph include;
Digraph exclude;
double length;
DirectedEdge next;

public TSPNode()
{
include = new Digraph(N);
exclude = new Digraph(N);
length = 0;
next = new DirectedEdge(0, 1, dis[0][1]);
}

public TSPNode(TSPNode node)
{
include = new Digraph(node.include);
exclude = new Digraph(node.exclude);
length = node.length;
next = new DirectedEdge(0, 1, dis[0][1]);
}

private DirectedEdge next(DirectedEdge edge)
{
int v = edge.from();
int w = edge.to() + 1;
if (w == v)
{
w += 1;
}
if (w >= N)
{
w = 0;
v += 1;
}
if (v >= N)
{
next = null;
} else
{
next = new DirectedEdge(v, w, dis[v][w]);
}
return next;
}

public void include(DirectedEdge edge)
{
length += dis[edge.from()][edge.to()];
next = next(edge);
}

public void exclude(DirectedEdge edge)
{
next = next(edge);
}

public List<Integer> tour()
{
List<Integer> cities = new LinkedList<Integer>();
int v = 0, w;
while (true)
{
Iterator<Integer> iter = include.adj(v).iterator();
if (iter.hasNext())
{
w = iter.next();
if (iter.hasNext())
{
return null;
}
if (w == 0)
{
if (cities.size() == N)
{
return cities;
}
return null;
}
v = w;
} else
{
return null;
}
}
}

public int size()
{
return include.E();
}

public double bound()
{
int[] in = new int[N];
int[] out = new int[N];
for (int i = 0; i < N; ++i)
{
in[i] = -1;
out[i] = -1;
}
for (int i = 0; i < N; ++i)
{
Iterator<Integer> iter = include.adj(i).iterator();
if (iter.hasNext())
{
int w = iter.next();
out[i] = w;
in[w] = i;
}
}

boolean[][] inexclude = new boolean[N][N];
boolean[][] outexclude = new boolean[N][N];

for (int i = 0; i < N; ++i)
{
Iterator<Integer> iter = exclude.adj(i).iterator();
while (iter.hasNext())
{
int w = iter.next();
outexclude[i][w] = true;
inexclude[w][i] = true;
}
}

double bnd = 0;
for (int i = 0; i < N; ++i)
{
if (in[i] == -1)
{
double minin = -1;
for (int j = 0; j < N; ++j)
{
if (j == i || inexclude[i][j])
{
continue;
}
if (minin < 0 || dis[j][i] < minin)
{
minin = dis[j][i];
}
}
if (minin < 0)
{
throw new RuntimeException(
"has no possible inbound vertex.");
}
bnd += minin;
}
else {
bnd += dis[in[i]][i];
}
}
for (int i = 0; i < N; ++i)
{
if (out[i] == -1)
{
double minout = -1;
for (int j = 0; j < N; ++j)
{
if (j == i || outexclude[i][j])
{
continue;
}
if (minout < 0 || dis[i][j] < minout)
{
minout = dis[i][j];
}
}
if (minout < 0)
{
throw new RuntimeException(
"has no possible outbound vertex.");
}
bnd += minout;
}
else {
bnd += dis[i][out[i]];
}
}
bnd /= 2;
return bnd;
}

public boolean isValid()
{
// check less than two adjacent edges(in and out) include for every
// vertex
int[] out = new int[N];
int[] in = new int[N];

for (int i = 0; i < N; ++i)
{
Iterator<Integer> iter = include.adj(i).iterator();
if (iter.hasNext())
{
out[i]++;
int w = iter.next();
in[w]++;
if (in[w] > 1)
{
return false;
}
if (iter.hasNext())
{
return false;
}
}
}
// check include + not exclude edges equal or larger than two for
// every
// vertex
int[] inexclude = new int[N];
int[] outexclude = new int[N];
for (int i = 0; i < N; ++i)
{
Iterator<Integer> iter = exclude.adj(i).iterator();
while (iter.hasNext())
{
outexclude[i]++;
int w = iter.next();
inexclude[w]++;
}
}
for (int i = 0; i < N; ++i)
{
if (inexclude[i] > N - 2)
{
return false;
}
if (outexclude[i] > N - 2)
{
return false;
}
}
// check cycle not exist or length equals N for include
DirectedCycle finder = new DirectedCycle(include);
if (finder.hasCycle())
{
int cnt = 0;
for (int v : finder.cycle())
{
cnt++;
}
if (cnt < N)
{
return false;
}
}
return true;
}
}

public TSPBranchAndBound(String file)
{
In in = new In(file);
dis = new double[N][N];
double[][] cities = new double[N][2];
for (int i = 0; i < N; ++i)
{
}
for (int i = 0; i < N; ++i)
{
for (int j = i + 1; j < N; ++j)
{
dis[i][j] = Math.sqrt(Math.pow(cities[i][0] - cities[j][0], 2)
+ Math.pow(cities[i][1] - cities[j][1], 2));
dis[j][i] = dis[i][j];
}
}

/*
for(int i = 0; i < N; ++i)
{
StdOut.print(i + ": ");
for(int j = 0; j < N; ++j)
{
StdOut.print((int)dis[i][j] + "\t");
}
StdOut.println();
}
*/

/*
int initialpath[] = {0, 1, 5, 9, 10, 11, 14, 18, 17, 21, 22, 20, 16, 19, 24, 23, 15, 13, 12, 8, 6, 2, 3, 7, 4, 0};
//int initialpath[] = {0, 1, 5, 10, 9, 11, 14, 18, 17, 21, 22, 20, 19, 24, 23, 15, 16, 13, 12, 8, 6, 2, 7, 3, 4, 0};
//int initialpath[] = {0, 1, 4, 3, 2, 0};
double cost = 0;
for (int i = 0; i < initialpath.length - 1; ++i)
{
cost += dis[initialpath[i]][initialpath[i + 1]];
}
StdOut.println("length: " + initialpath.length + ", cost: " + cost);
*/
/*
* mincost = 0; for (int i = 0; i < N - 1; ++i) { mincost += dis[i][i +
* 1]; } mincost += dis[N - 1][0]; StdOut.println("inital mincost: " +
* mincost);
*/
mincost = Double.POSITIVE_INFINITY;
//mincost = 26443;
tour = new LinkedList<Integer>();

TSPNode node = new TSPNode();
branch(node);
}

private void branch(TSPNode node)
{
if (node.size() == N)
{
//assert node.length == node.bound() : "length and bound not equal";
StdOut.println("old: " + mincost + ", new: " + node.length);
if (node.length < mincost)
{
mincost = node.length;
tour = node.tour();
}
return;
}
if (node.next == null)
{
return;
}

DirectedEdge next = node.next;
TSPNode with = new TSPNode(node);
with.include(next);
TSPNode without = new TSPNode(node);
without.exclude(next);

if (!with.isValid())
{
if (without.isValid())
{
double withoutbnd = without.bound();
if (withoutbnd < mincost)
{
branch(without);
}
}
} else
{
if (!without.isValid())
{
double withbnd = with.bound();
if (withbnd < mincost)
{
branch(with);
}
} else
{
double withbnd = with.bound(), withoutbnd = without.bound();
if (withbnd > withoutbnd)
{
if (withoutbnd < mincost)
{
branch(without);
}
if (withbnd < mincost)
{
branch(with);
}
} else
{
if (withbnd < mincost)
{
branch(with);
}
if (withoutbnd < mincost)
{
branch(without);
}
}
}
}
}

public void report()
{
StdOut.println("mincost: " + mincost + "\n");
for (int i = 0; i < tour.size(); ++i)
{
StdOut.print(tour.get(i));
if (i != tour.size() - 1)
{
StdOut.print(", ");
} else
{
StdOut.println();
}
}
}

public static void main(String[] args)
{
long start = System.nanoTime();
TSPBranchAndBound tsp = new TSPBranchAndBound("tsp.txt");
tsp.report();
StdOut.println("time elapsed: " + ((double)System.nanoTime() - start) / 1000000000);
}
}


import pylab
import sys

dash_style = (
(0, 20, -15, 30, 10),
(1, 30, 0, 15, 10),
(0, 40, 15, 15, 10),
(1, 20, 30, 60, 10),
)

fig = pylab.figure()

with open(sys.argv[1], "r") as f:
for i in range(n):
x, y = [float(x) for x in f.readline().split()]
ax.plot(x, y, marker='o')
(dd, dl, r, dr, dp) = dash_style[1 if i == 22 else (i % 2)]
#print 'dashlen call', dl
t = ax.text(x, y, str(i), withdash=True,
dashdirection=dd,
dashlength=dl,
rotation=r,
dashrotation=dr,
dashpush=dp,
)
#ax.set_xlim((20000, 5.0))
#ax.set_ylim((0.0, 5.0))
pylab.show()

01-09 3995
03-13

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客