This repository has been archived on 2021-10-31. You can view files and clone it, but cannot push or open issues or pull requests.
AICup/code/opt.cc

85 lines
2.2 KiB
C++

// vim: set ts=2 sw=2 et tw=80:
#include "opt.h"
using namespace std;
typedef unsigned int uint;
typedef tuple<uint, uint, uint> triple;
ostream& operator<< (ostream& out, vector<uint> a) {
out << "[";
for (int i = 0; i < a.size() - 1; i++) {
out << a[i] << ",";
}
out << a[a.size() - 1] << "]";
return out;
}
ostream& operator<< (ostream& out, triple& a) {
out << "(" << get<0>(a) << "," << get<1>(a) << "," << get<2>(a) << ")";
return out;
}
double reverse_segment_if_better(vector<uint>& tour, const double (&dist_matrix) [1577][1577],
uint i, uint j, uint k) {
uint A = tour[i-1];
uint B = tour[i];
uint C = tour[j-1];
uint D = tour[j];
uint E = tour[k-1];
uint F = tour[k % (tour.size()-1)];
double d0 = (dist_matrix[A][B] + dist_matrix[C][D] + dist_matrix[E][F]);
double d1 = (dist_matrix[A][C] + dist_matrix[B][D] + dist_matrix[E][F]);
double d2 = (dist_matrix[A][B] + dist_matrix[C][E] + dist_matrix[D][F]);
double d3 = (dist_matrix[A][D] + dist_matrix[E][B] + dist_matrix[C][F]);
double d4 = (dist_matrix[F][B] + dist_matrix[C][D] + dist_matrix[E][A]);
if (d0 > d1) {
reverse(tour.begin() + i, tour.begin() + j);
return -d0 + d1;
}
else if (d0 > d2) {
reverse(tour.begin() + j, tour.begin() + k);
return -d0 + d2;
}
else if (d0 > d4) {
reverse(tour.begin() + i, tour.begin() + k);
return -d0 + d4;
}
else if (d0 > d3) {
vector<uint> tmp;
for (uint z = j; z < k; z++) {
tmp.push_back(tour[z]);
}
for (uint z = i; z < j; z++) {
tmp.push_back(tour[z]);
}
for (uint f = i; f < k; f++) {
tour[f] = tmp[f - i];
}
return -d0 + d3;
}
return 0;
}
void three_opt(vector<uint>& tour, const double (&dist_matrix) [1577][1577], double& sh_dist) {
double delta = 0;
uint n = tour.size() - 1;
for (uint i = 0; i < 1; i++) {
for (uint i = 1; i < n; i++)
for (uint j = i+2; j < n; j++)
for (uint k = j+2; k < n; k++) {
double d = reverse_segment_if_better(tour, dist_matrix, i, j, k);
if (d > 0) cerr << d << " " << i << "," << j << "," << k << endl;
delta += d;
}
if (delta >= 0)
break;
}
sh_dist += delta;
}