Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- //#define NN_SIMPLE_TEST 0
- //#define NN_RANDOM_TEST 1
- #define TWO_OPT_TEST 2
- using namespace std;
- #define MAX 105
- struct Point {
- double x;
- double y;
- Point() {
- }
- Point(double a, double b) {
- x = a;
- y = b;
- }
- double deg2rad(double deg) {
- return deg * (3.14159 / 180);
- }
- double getDistanceFromLatLonInKm(double lat1, double lon1, double lat2, double lon2) {
- double R = 6371; // Radius of the earth in km
- double dLat = deg2rad(lat2 - lat1); // deg2rad below
- double dLon = deg2rad(lon2 - lon1);
- double a = sin(dLat / 2.0) * sin(dLat / 2.0) +
- cos(deg2rad(lat1)) * cos(deg2rad(lat2)) * sin(dLon / 2) * sin(dLon / 2);
- double c = 2 * atan2(sqrt(a), sqrt(1 - a));
- double d = R * c; // Distance in km
- return d;
- }
- double dist(Point other) {
- return getDistanceFromLatLonInKm(x, y, other.x, other.y);
- // return hypot(x - other.x, y - other.y);
- }
- };
- int n;
- Point pt[MAX];
- bool Vis[MAX];
- vector<int> Tour;
- int bestStartNNSimple;
- class distAndPoint {
- public:
- Point p;
- int d;
- int realIdx;
- distAndPoint() {
- }
- distAndPoint(Point pp, int x, int ridx) {
- p = pp;
- d = x;
- realIdx = ridx;
- }
- bool operator<(const distAndPoint &dp) {
- return (d < dp.d);
- }
- };
- double Cost(vector<int> Tour) {
- double Ans = 0;
- int Size = (int) Tour.size();
- for (int i = 0; i < Size; i++) {
- int xx = Tour[i];
- int yy = Tour[(i + 1) % Size];
- Ans += pt[xx].dist(pt[yy]);
- }
- return Ans;
- }
- void PrintSolution(vector<int> Tour) {
- printf("Solution Cost : %lf\n", Cost(Tour));
- printf("Tour Description : ");
- for (int i = 0; i < Tour.size(); i++)
- printf("%d ", Tour[i]);
- printf("\n\n");
- }
- class nnTourObject {
- public:
- vector<int> tourList;
- int cost;
- nnTourObject() {}
- double Cost() {
- double Ans = 0;
- int Size = static_cast<int>(tourList.size());
- for (int i = 0; i < Size; i++) {
- int xx = tourList[i];
- int yy = tourList[(i + 1) % Size];
- Ans += pt[xx].dist(pt[yy]);
- }
- return Ans;
- }
- nnTourObject(vector<int> v) {
- tourList = v;
- cost = static_cast<int>(Cost());
- }
- bool operator<(const nnTourObject &nt) {
- return (cost < nt.cost);
- }
- };
- vector<nnTourObject> nnGreedySimple_5_Tours;
- vector<nnTourObject> nnGreedyRandom_5_Tours;
- vector<nnTourObject> twoOptFirst_4_Tours;
- vector<nnTourObject> twoOptBest_4_Tours;
- void printVector(vector<int> vec) {
- for (int i = 0; i < vec.size(); i++) {
- cout << vec[i] << " ";
- }
- cout << endl;
- }
- /*****************NN Simple Start**********************/
- int FindNearestUnvisited(int x) {
- double Min = LLONG_MAX;
- int Idx = -1;
- for (int i = 0; i < n; i++) {
- if (Vis[i])
- continue;
- if (pt[x].dist(pt[i]) < Min) {
- Min = pt[x].dist(pt[i]);
- Idx = i;
- }
- }
- return Idx;
- }
- void nnGreedySimple(int startIdx) {
- Tour.clear();
- memset(Vis, 0, sizeof(Vis));
- int Start = startIdx;
- int Last = Start;
- Vis[Last] = 1;
- Tour.push_back(Start);
- while (Tour.size() < n) {
- int Idx = FindNearestUnvisited(Last);
- Vis[Idx] = 1;
- Tour.push_back(Idx);
- }
- }
- vector<nnTourObject> nnGreedySimpleUtil() {
- vector<nnTourObject> nn_5_Tours;
- int t = 0;
- while (t < 5) {
- t++;
- int randomStart = rand() % n;
- nnGreedySimple(randomStart);
- nnTourObject nnTour(Tour);
- nn_5_Tours.push_back(nnTour);
- }
- sort(nn_5_Tours.begin(), nn_5_Tours.end());
- #ifdef NN_SIMPLE_TEST
- cout << "Nearest Neighbor Greedy Simple Tour: " << endl;
- cout << "Best Case: " << endl;
- cout << " Start Node: " << nn_5_Tours[0].tourList[0] << endl;
- cout << " Tour : ";
- printVector(nn_5_Tours[0].tourList);
- cout << " Cost: " << nn_5_Tours[0].cost << endl;
- #endif
- bestStartNNSimple = nn_5_Tours[0].tourList[0];
- #ifdef NN_SIMPLE_TEST
- cout << "Worst Case: " << endl;
- cout << " Start Node: " << nn_5_Tours[4].tourList[0] << endl;
- cout << " Tour : ";
- printVector(nn_5_Tours[4].tourList);
- cout << " Cost: " << nn_5_Tours[4].cost << endl;
- #endif
- double sum = 0;
- for (int i = 0; i < nn_5_Tours.size(); i++) {
- sum += nn_5_Tours[i].cost;
- }
- sum = sum / nn_5_Tours.size();
- #ifdef NN_SIMPLE_TEST
- cout << "Average Cost: " << sum << endl;
- #endif
- nnGreedySimple_5_Tours = nn_5_Tours;
- return nn_5_Tours;
- }
- /*****************NN Simple End**********************/
- /***********NN Random Start***************/
- int FindNearestRandomUnvisited(int x) {
- vector<distAndPoint> nearest_nodes;
- for (int i = 0; i < n; i++) {
- if (!Vis[i]) {
- distAndPoint tem(pt[i], pt[x].dist(pt[i]), i);
- nearest_nodes.push_back(tem);
- }
- }
- sort(nearest_nodes.begin(), nearest_nodes.end());
- int divisor = 5;
- if (nearest_nodes.size() < 5) divisor = static_cast<int>(nearest_nodes.size());
- int randomIdx = rand() % divisor;
- distAndPoint tem = nearest_nodes[randomIdx];
- int Idx = tem.realIdx;
- return Idx;
- }
- void nnGreedyRandomized(int startIdx) {
- Tour.clear();
- memset(Vis, 0, sizeof(Vis));
- int Start = startIdx;
- int Last = Start;
- Vis[Last] = true;
- Tour.push_back(Start);
- while (Tour.size() < n) {
- int Idx = FindNearestRandomUnvisited(Last);
- Vis[Idx] = true;
- Tour.push_back(Idx);
- }
- }
- vector<nnTourObject> nnGreedyRandomizedUtil() {
- vector<nnTourObject> nn_5_Tours;
- vector<nnTourObject> simpleNNTour;
- int t = 0;
- while (t < 10) {
- t++;
- nnGreedyRandomized(bestStartNNSimple);
- nnTourObject nnTour(Tour);
- nn_5_Tours.push_back(nnTour);
- }
- sort(nn_5_Tours.begin(), nn_5_Tours.end());
- #ifdef NN_RANDOM_TEST
- cout << "Nearest Neighbor Greedy Randomized Tour: " << endl;
- cout << "Best Case: " << endl;
- cout << " Start Node: " << nn_5_Tours[0].tourList[0] << endl;
- cout << " Tour : ";
- printVector(nn_5_Tours[0].tourList);
- cout << " Cost: " << nn_5_Tours[0].cost << endl;
- cout << "Worst Case: " << endl;
- cout << " Start Node: " << nn_5_Tours[4].tourList[0] << endl;
- cout << " Tour : ";
- printVector(nn_5_Tours[4].tourList);
- cout << " Cost: " << nn_5_Tours[4].cost << endl;
- #endif
- double sum = 0;
- for (int i = 0; i < nn_5_Tours.size(); i++) {
- sum += nn_5_Tours[i].cost;
- }
- sum = sum / nn_5_Tours.size();
- #ifdef NN_RANDOM_TEST
- cout << "Average Cost: " << sum << endl;
- #endif
- nnGreedyRandom_5_Tours = nn_5_Tours;
- return nn_5_Tours;
- }
- /***********NN Random End***************/
- /************2-Opt First improve Start***************/
- void TwoOptHeuristicFirstImprovement(vector<int> vec) {
- Tour.clear();
- memset(Vis, 0, sizeof(Vis));
- Tour = vec;
- while (true) {
- double Curr = Cost(Tour);
- bool Changed = false;
- for (int i = 0; i < Tour.size(); i++) {
- for (int j = i + 2; j < Tour.size(); j++) {
- reverse(Tour.begin() + i + 1, Tour.begin() + j + 1);
- double NewCost = Cost(Tour);
- if (NewCost < Curr) {
- Changed = true;
- break;
- }
- reverse(Tour.begin() + i + 1, Tour.begin() + j + 1);
- }
- if (Changed)
- break;
- }
- if (!Changed)
- break;
- }
- }
- /***************2-Opt best improve start***********/
- void TwoOptHeuristicBestImprovement(vector<int> vec) {
- int ii = 0, jj = 0;
- Tour.clear();
- memset(Vis, 0, sizeof(Vis));
- Tour = vec;
- while (true) {
- double Curr = Cost(Tour);
- bool Changed = false;
- for (int i = 0; i < Tour.size(); i++) {
- for (int j = i + 2; j < Tour.size(); j++) {
- reverse(Tour.begin() + i + 1, Tour.begin() + j + 1);
- double NewCost = Cost(Tour);
- if (NewCost < Curr) {
- Changed = true;
- ii = i;
- jj = j;
- Curr = NewCost;
- }
- reverse(Tour.begin() + i + 1, Tour.begin() + j + 1);
- }
- if (Changed) {
- reverse(Tour.begin() + ii + 1, Tour.begin() + jj + 1);
- break;
- }
- }
- if (!Changed)
- break;
- }
- }
- // twoOptType == 1 -> First , 2 -> Best
- // NNorSH == 1 -> NN , 2 -> SH
- vector<nnTourObject> twoOptUtil(int NNorSH, int twoOptType) {
- string name = "";
- vector<nnTourObject> myTourResults;
- vector<nnTourObject> bestToursOfNNHandSH;
- if (NNorSH == 1) {
- bestToursOfNNHandSH.push_back(nnGreedyRandom_5_Tours[0]);
- bestToursOfNNHandSH.push_back(nnGreedyRandom_5_Tours[1]);
- bestToursOfNNHandSH.push_back(nnGreedyRandom_5_Tours[2]);
- bestToursOfNNHandSH.push_back(nnGreedySimple_5_Tours[0]);
- if (twoOptType == 1) {
- for (int i = 0; i < bestToursOfNNHandSH.size(); i++) {
- TwoOptHeuristicFirstImprovement(bestToursOfNNHandSH[i].tourList);
- nnTourObject tem(Tour);
- myTourResults.push_back(tem);
- }
- name = "2-Opt First for NNH Greedy Random." ;
- } else if(twoOptType == 2)
- {
- for (int i = 0; i < bestToursOfNNHandSH.size(); i++) {
- TwoOptHeuristicBestImprovement(bestToursOfNNHandSH[i].tourList);
- nnTourObject tem(Tour);
- myTourResults.push_back(tem);
- }
- name = "2-Opt Best for NNH Greedy Random." ;
- }
- } else if (NNorSH == 2) {
- //SH vectors go here.
- // bestToursOfNNHandSH.push_back(shGreedyRandom_5_Tours[0]);
- // bestToursOfNNHandSH.push_back(shGreedyRandom_5_Tours[1]);
- // bestToursOfNNHandSH.push_back(shGreedyRandom_5_Tours[2]);
- // bestToursOfNNHandSH.push_back(shGreedySimple_5_Tours[0]);
- //
- // if (twoOptType == 1) {
- // for (int i = 0; i < bestToursOfNNHandSH.size(); i++) {
- // TwoOptHeuristicFirstImprovement(bestToursOfNNHandSH[i].tourList);
- // nnTourObject tem(Tour);
- // myTourResults.push_back(tem);
- // }
- //name = "2-Opt First for SH Greedy Random." ;
- // } else if(twoOptType == 2)
- // {
- // for (int i = 0; i < bestToursOfNNHandSH.size(); i++) {
- // TwoOptHeuristicBestImprovement(bestToursOfNNHandSH[i].tourList);
- // nnTourObject tem(Tour);
- // myTourResults.push_back(tem);
- // }
- //name = "2-Opt First for SH Greedy Random." ;
- // }
- }
- sort(myTourResults.begin(), myTourResults.end());
- #ifdef TWO_OPT_TEST
- cout << name << " : " << endl;
- cout << "Best Case: " << endl;
- cout << " Start Node: " << myTourResults[0].tourList[0] << endl;
- cout << " Tour : ";
- printVector(myTourResults[0].tourList);
- cout << " Cost: " << myTourResults[0].cost << endl;
- cout << "Worst Case: " << endl;
- cout << " Start Node: " << myTourResults[myTourResults.size()-1].tourList[0] << endl;
- cout << " Tour : ";
- printVector(myTourResults[myTourResults.size()-1].tourList);
- cout << " Cost: " << myTourResults[myTourResults.size()-1].cost << endl;
- #endif
- double sum = 0;
- for (int i = 0; i < myTourResults.size(); i++) {
- sum += myTourResults[i].cost;
- }
- sum = sum / myTourResults.size();
- #ifdef TWO_OPT_TEST
- cout << "Average Cost: " << sum << endl;
- #endif
- return myTourResults;
- }
- int main() {
- // freopen("pr76.tsp", "r", stdin);
- freopen("berlin52.tsp", "r", stdin);
- // freopen("st70.tsp", "r", stdin);
- freopen("out.txt", "w", stdout);
- srand(time(NULL));
- scanf("%d", &n);
- for (int i = 0; i < n; i++) { scanf("%lf %lf", &pt[i].x, &pt[i].y); }
- /***************Run NN_Greedy_Simple()*****************/
- nnGreedySimple_5_Tours = nnGreedySimpleUtil();
- nnGreedyRandom_5_Tours = nnGreedyRandomizedUtil();
- twoOptFirst_4_Tours = twoOptUtil(1,2);
- // (nnsh, twoOptType)..
- // NNorSH == 1 -> NN , 2 -> SH
- // twoOptType == 1 -> First , 2 -> Best
- vector<nnTourObject> vn;
- vn = twoOptFirst_4_Tours;
- for (int i = 0; i < vn.size(); i++) {
- cout << "################## Tour No. " << i + 1 << " : Cost = " << vn[i].Cost()
- << " ################" << endl;
- printVector(vn[i].tourList);
- cout << "###########################################################" << endl;
- }
- cout << "****************************************************************************" << endl ;
- twoOptBest_4_Tours = twoOptUtil(1, 1);
- vn = twoOptBest_4_Tours;
- for (int i = 0; i < vn.size(); i++) {
- cout << "################## Tour No. " << i + 1 << " : Cost = " << vn[i].Cost()
- << " ################" << endl;
- printVector(vn[i].tourList);
- cout << "###########################################################" << endl;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement