算法实验2-1

TSP问题


算法实验二第一题,动态规划处理tsp问题,要求:从任意城市出发,走过所有城市再回到出发点,求最短路径,
2021.5.12. 0:31分
正在学习实现问题要求ing
代码已经解决从0点出发,回到0点的最短路径,明天接着写,困了睡觉嘻嘻
(这个还要交实验报告,老师应该不查重吧,版权还是自个儿的,不可能自己抄自己么)
2021.5.12. 14:21
上午第二节没课,写了一个小时,下午再写一小时完成实验

//TSP问题
#include<bits/stdc++.h>
using namespace std;

//二进制运算,生成子集
vector<int> print_subset(int n, int s,int c)
{
	vector<int> exchange;
	for (int i = 0; i < n ; i++)
	{
		if (s & (1 << i))
		{
			if (i == c)
			{
				exchange.clear();
				break;
			}
			else 
			{
				exchange.push_back(i);
			}
		}
	}
	return exchange;
}

//判断数字n是否存在于vector数组w中
bool search_i(vector<int> w, int n)
{
	bool t = false;
	for (int i = 0; i < w.size(); i++)
	{
		if (n == w[i]) 
		{
			t = true;
			break;
		}
	}
	return t;
}


int road[100][100] = {}; //存输入路径
int value[100][100] = {};//存计算结果的表
int new_road[100][100] = {};//新路径

//存储各个生成子集
struct a {
	vector<int> w;
}number[100];


//存储路径
struct b {
	vector<int>path;
}num_path[100][100];

int main()
{
	vector <int> exchange;
	vector <int> index;
	int count = 1;
	int count2 = 0;
	int count3 = 0;
	int min = 0;
	int n, c;


    //输入部分
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{   //if i==j  cin>>0
			cin >> road[i][j];
		}
	}
	std::cout << "从顶点: ";
	std::cin >> c;
	std::cout << "出发\n";


	//换图
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			if (i == 0 && j==0)
			{
				new_road[i][j] = road[c][c];
			}
			else
			if (i == c && j == c)
			{
				new_road[i][j] = road[0][0];
			}
			else 
			if (i == 0 && j != 0)
			{
				if (j == c)
				{
					new_road[i][j] = road[c][0];
				}
				else
				{
					new_road[i][j] = road[c][j];
				}
			}
			else
			if(i != 0 && j == 0)
			{
				if (i == c)
				{
					new_road[i][j] = road[0][c];
				}
				else
				{ 
				new_road[i][j] = road[i][c];
			    }
			}
			else
			if (i == c && j != c)
			{
				if (j == 0)
				{
					new_road[i][j] = road[0][c];
				}
				else 
				{
					new_road[i][j] = road[0][j];
				}
			}
			else
			if (i != c && j == c)
			{
				if (i == 0)
				{
					new_road[i][j] = road[c][0];
				}
				else
				{
					new_road[i][j] = road[i][0];
				}
			}
			else
			{
				new_road[i][j] = road[i][j];
			}
		}
	}


	//输出换好的图
	cout << "根据出发点调整road路径图,使得出发点c与0全部兑换:\n";
	cout << "新图第一行表头实际上对应的原各个点为:\n";
	for (int i = 0; i < n; i++)
	{
		if (i == 0)
			cout <<c<< " ";
		else
			if (i == c)
				cout << "0 ";
			else
				cout << i << " ";
	}
	cout << endl;
	cout << "新图:\n";
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			printf("%d ", new_road[i][j]);
		}
		cout << endl;
	}


	//求生成子集
	for (int i = 0; i < (1 << n); i++)
	{
		count2 = 0;
		exchange=print_subset(n, i, 0);//取生成子集
		while (exchange.empty()==0)//存储生成子集
		{
			number[count].w.push_back(exchange.back());
			exchange.pop_back();
			count2++;
		}
		if (count2!=0)
		{
			count++;
		}
	}


	cout  << "输出生成子集为:\n";
	//输出生成子集,查看它们
	for (int i = 1; i <= count; i++)
	{
		for (int j = 0; j < number[i].w.size(); j++)
		{
			std::cout << number[i].w[j];
		}
		if (i != count - 1)
		{
			std::cout << endl;
		}
	}


	//置表,第0列
	for (int i = 1; i < n; i++)
	{
		value[i][0] = new_road[i][0];
	}


	//置路径表,第0列
	for (int i = 1; i < n; i++)
	{
		num_path[i][0].path.push_back(0);
		num_path[i][0].path.push_back(i);
	}





	int min_x = 0;
	int count5 = 0;
	int In = 0;
	int Jk = 0;
	int IJ_count3 = 0;
	int change = 0;
	//计算表,1 ~ 2^(n-1)-1 列
	for (int j = 1; j <= count-1; j++)
	{//历遍列,即历遍生成子集,子集里元素:接下来要依次走过并在都走过之后返回0点
		for (int i = 1; i < n; i++)
		{//历遍行
			if (!search_i(number[j].w, i))//该行行数的点不在子集中,可以从该点出发依次走过子集元素,需要计算填表
			{
				min = 0;
	            count5 = 0;  min_x = 0;
				In = 0; Jk = 0; IJ_count3 = 0;
				//priority_queue <int, vector<int>, greater<int> > q;//小顶堆升序队列,辅助求最小值
				for (int k = 0; k < number[j].w.size(); k++)
				{//历遍子集元素
					


					//找count3
					if (index.empty() == 0)
					{
						index.clear();
					}
						for (int t = 0; t < number[j].w.size(); t++)
						{//主要在于求解 value[number[j].w[k][  ?  ]  的 " ? " 的内容," ? "为抛去w[k]之后剩余的子集元素集合,该集合由index数组存储
							if (number[j].w[t] != number[j].w[k])
							{
								index.push_back(number[j].w[t]);
							}
						}
					    count3 = 0;
					    while (index.empty() == 0)//计算求解 count3
						{
							count3 += pow(2,index.back()-1);
							index.pop_back();
						}




						//找最小值
						min_x = new_road[i][number[j].w[k]] + value[number[j].w[k]][count3];
						if (count5 == 0)
						{
							min = min_x;
							In = i; Jk = number[j].w[k]; IJ_count3 = count3;
						}
						else 
						{
							if (min_x < min)
							{
								min = min_x;
								In = i; Jk = number[j].w[k]; IJ_count3 = count3;
							}
						}
						count5++;
						//q.push(new_road[i][number[j].w[k]] + value[number[j].w[k]][count3]);
				}


				//处理最短路径的总长度大小
				value[i][j] =min;


				//处理最短路径的向量解
				num_path[i][j].path = num_path[Jk][IJ_count3].path;
				//cout << Jk << "  " << IJ_count3 << endl;
				num_path[i][j].path.push_back(i);
				cout<<"表中对应的点坐标: " << i << "  " << j << endl;
				cout << "对应的片段路径:";
				for (int g = num_path[i][j].path.size()-1; g >= 0 ; g--)
				{
					cout << num_path[i][j].path[g]<<"  ";
				}
				cout << endl;


			}
		}
	}
	

	//计算  第0行,出发点为0时的最短路径长度
	int min2 = 0;
	int count4 = 0;
	vector<int> index2;
	int min_x2 = 0;
	int count6 = 0;
	int In2 = 0;
	int Jk2 = 0;
	int IJ_count4 = 0;
	//priority_queue <int, vector<int>, greater<int> > q_sum;// 辅助计算最小值
	for (int j = 1; j < n; j++)
	{
		if (index2.empty() == 0)
		{
			index2.clear();
		}
		for (int t = 0; t <number[count-1].w.size() ; t++)
		{
			if (number[count-1].w[t]!= j)
			{
				index2.push_back(number[count-1].w[t]);
			}
		}
		count4 = 0;
		while (index2.empty() == 0)
		{
			count4 += pow(2, index2.back() - 1);
			index2.pop_back();
		}





		//找最小值
		min_x2 = new_road[0][j] + value[j][count4];
		if (count6 == 0)
		{
			min2 = min_x2;
			In2 = 0; Jk2 = j; IJ_count4 = count4;
		}
		else
		{
			if (min_x2 < min2)
			{
				min2 = min_x2;
				In2 = 0; Jk2 = j; IJ_count4 = count4;
			}
		}
		count6++;

	}
	//处理最短路径的总长度大小
	value[0][count - 1] = min2;


	//处理最短路径长度的向量解
	for (int h = 0; h < num_path[Jk2][IJ_count4].path.size(); h++)
	{
		num_path[0][count-1].path.push_back(num_path[Jk2][IJ_count4].path[h]);
	}
	num_path[0][count-1].path.push_back(0);


	//输出表
	std::cout << "                   ";
	for (int i = 1; i <= count; i++)
	{
		for (int j = 0; j < number[i].w.size(); j++)
		{
			printf("%d", number[i].w[j]);
		}
		std::cout << "        ";
	}
	std::cout << endl;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < count; j++)
		{
			printf("%9d ", value[i][j]);
		}
		std::cout << endl;
	}
	 


	cout << "新图的最短路径如下: \n";
	for (int i = num_path[0][count - 1].path.size() - 1; i >= 0; i--)
	{
		cout << num_path[0][count - 1].path[i] << "  ";
	}
	cout << endl;

	//输入的路径图被换过,再换回正确顺序
	for (int i = 0; i < num_path[0][count - 1].path.size() ; i++)
	{
		if (num_path[0][count - 1].path[i] == 0)
		{
			num_path[0][count - 1].path[i] = c;
		}
		else
		if (num_path[0][count - 1].path[i] == c)
		{
			num_path[0][count - 1].path[i] = 0;
		}
	}


	//最短路径向量解输出
	cout << "实际最短路径如下: \n";
	for (int i = num_path[0][count - 1].path.size()-1; i >=0 ; i--)
	{
		cout << num_path[0][count - 1].path[i]<<"  ";
	}

}

在这里插入图片描述

posted @ 2021-05-12 00:31  在天边偷看小天使  阅读(8)  评论(0)    收藏  举报  来源