Добавил:
t.me Прошиваю/настраиваю роутеры в общаге МИЭТ, пишите в тг: t.me/aogudugnp Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

аисд / lab4 / Main

.cpp
Скачиваний:
0
Добавлен:
17.08.2025
Размер:
5.74 Кб
Скачать
#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;
}
Соседние файлы в папке lab4