
Добавил:
vgost
t.me
Прошиваю/настраиваю роутеры в общаге МИЭТ, пишите в тг: t.me/aogudugnp
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
#include "MatrixOperations.h"
#include <locale>
#include <queue>
std::pair<int, int> MaxPenalty(const std::vector<std::vector<int>>& vec, int& maxPenalty)
{
int len = vec.size();
std::pair<int, int> maxPenaltyIdx;
maxPenalty = 0;
std::vector<std::vector<int>> penaltyMatrix;
penaltyMatrix.resize(len);
for (int i = 0; i < len; i++)
penaltyMatrix[i].resize(len, 0);
for (int i = 0; i < vec.size(); i++)
for (int j = 0; j < vec[i].size(); j++)
{
if (vec[i][j] != 0)
continue;
int rowMin = Limits(INF);
int colMin = Limits(INF);
for (int k = 0; k < len; k++)
if (rowMin > vec[i][k] && k != j)
rowMin = vec[i][k];
for (int k = 0; k < len; k++)
if (colMin > vec[k][j] && k != i);
colMin = vec[k][j];
penaltyMatrix[i][j] = rowMin + colMin;
if (penaltyMatrix[i][j] > maxPenalty || penaltyMatrix[i][j] != Limits(INF))
{
maxPenalty = penaltyMatrix[i][j];
maxPenaltyIdx.first = i;
maxPenaltyIdx.second = j;
}
}
std::cout << "Расчет штрафов для нулевых элементов: " << std::endl;
OutputMatrix(penaltyMatrix);
std::cout << std::endl << std::endl;
return maxPenaltyIdx;
}
bool cycleCheck(std::vector<std::pair<int, int>> path, std::pair<int, int> newEdge)
{
if (path.size() < 2)
return false;
std::vector<int> sources;
std::vector<int> destinations;
for (auto& it : path)
{
sources.push_back(it.first);
destinations.push_back(it.second);
}
return (std::find(sources.begin(), sources.end(), newEdge.second) != sources.end()
&& std::find(destinations.begin(), destinations.end(), newEdge.first) != destinations.end());
}
auto nodeCompare = [](const Node& left, const Node& right)
{
return left.lowerBound > right.lowerBound;
};
Node TSPsolve(std::vector<std::vector<int>> vec)
{
std::priority_queue<Node, std::vector<Node>, decltype(nodeCompare)> nodeQueue(nodeCompare);
OutputMatrix(vec);
std::cout << std::endl << std::endl;
int localLowerBound = ReduceMatrix(vec);
// init initial indices for intital matrix
std::vector<int> rootRealRows;
std::vector<int> rootRealCols;
for (int i = 0; i < vec.size(); i++)
{
rootRealRows.push_back(i);
rootRealCols.push_back(i);
}
// end
// create root (as working matrix)
Node root(vec, rootRealRows, rootRealCols, std::vector<std::pair<int, int>>(), localLowerBound, 0);
std::cout << "Глобальная нижняя граница: " << localLowerBound << std::endl;
//
nodeQueue.push(root);
while (!nodeQueue.empty())
{
Node current = nodeQueue.top();
if (current.pathLen == vec.size() - 1)
{
current.path.push_back(std::make_pair(current.matrixRealRows[0], current.matrixRealCols[0]));
std::cout << "Путь: " << std::endl;
for (auto& it : current.path)
std::cout << it.first << " -> " << it.second << std::endl;
return current;
}
std::cout << "Рассматриваем путь: " << std::endl;
for (auto& it : current.path)
std::cout << it.first << " -> " << it.second << std::endl;
std::cout << std::endl << std::endl;
std::cout << "Матрица весов на данном шаге: " << std::endl;
OutputMatrix(current.matrix);
std::cout << std::endl << std::endl;
int maxPenalty = 0;
std::pair<int, int> maxPenaltyIdx = MaxPenalty(current.matrix, maxPenalty);
std::cout << "Максимальный штраф находится на позиции: (" <<
current.matrixRealRows[maxPenaltyIdx.first] << ", " <<
current.matrixRealCols[maxPenaltyIdx.second] << "), он равен " << maxPenalty << std::endl;
std::vector<int> firstChildRealRows = current.matrixRealRows;
std::vector<int> firstChildRealCols = current.matrixRealCols;
auto firstChildPath = current.path;
auto firstChildMatr = deleteRowAndColFromMatrix(current.matrix,
firstChildRealRows, firstChildRealCols, maxPenaltyIdx.first, maxPenaltyIdx.second, firstChildPath);
Node firstChild(firstChildMatr, firstChildRealRows, firstChildRealCols,
firstChildPath, current.lowerBound, current.pathLen + 1);
firstChild.lowerBound += ReduceMatrix(firstChild.matrix);
nodeQueue.pop();
Node secondChild(current.matrix, current.matrixRealRows, current.matrixRealCols,
current.path, current.lowerBound + maxPenalty, current.pathLen);
secondChild.matrix[maxPenaltyIdx.first][maxPenaltyIdx.second] = Limits(INF);
if (!cycleCheck(firstChild.path, firstChild.path[firstChild.path.size() - 1]) || firstChild.pathLen == vec.size() - 1)
nodeQueue.push(firstChild);
nodeQueue.push(secondChild);
}
}
int main()
{
setlocale(LC_ALL, "Rus");
system("chcp 1251 < nul");
//const int N = 5;
//int costMatrix[N][N] =
//{
// { Limits(INF) , 10 , 15 , 9 , 7 },
// { 10 , Limits(INF) , 10 , 5 , 6 },
// { 15 , 10 , Limits(INF) , 8 , 9 },
// { 9 , 5 , 8 , Limits(INF) , 6 },
// { 7 , 6 , 9 , 6 , Limits(INF) },
//};
const int N = 7;
int costMatrix[N][N] =
{
{ Limits(INF), 10 , 15 , 9 , 7 , 50 , 59 },
{ 10 , Limits(INF), 10 , 5 , 6 , 51 , 43 },
{ 15 , 10 , Limits(INF), 8 , 9 , 32 , 43 },
{ 9 , 5 , 8 , Limits(INF), 6 , 11 , 35 },
{ 7 , 6 , 9 , 6 , Limits(INF), 56 , 33 },
{ 50 , 51 , 32 , 11 , 56 , Limits(INF), 51 },
{ 59 , 43 , 43 , 35 , 33 , 51 , Limits(INF)}
};
std::vector<std::vector<int>> costvec;
costvec.resize(N);
for (int i = 0; i < N; i++)
{
costvec[i].reserve(N);
for (int j = 0; j < N; j++)
{
costvec[i].push_back(costMatrix[i][j]);
}
}
int pathLen = 0;
Node solution = TSPsolve(costvec);
for (auto& it : solution.path)
{
pathLen += costvec[it.first][it.second];
}
std::cout << "Длина пути: " << pathLen << std::endl;
system("pause");
return 0;
}