TSP问题

问题 K: 送外卖

题目描述

在美团和饿了么大行其道的今天,囊中羞涩的小周和小美,也随大流加入了配送员的行列。每天下课后,他们都去堕落街帮北京烤鸭店送外卖。

过了好些日子,小周发现每次送外卖,小美总比自己先回来,就算自己拼命跑啊跑,也总是比她慢,明明小美也是和自己一样,走着去送外卖的(等外卖的都饿死了╮(╯﹏╰)╭)。

小周忍不住问了小美这是怎么回事,小美说:“笨蛋,本小姐每次出去都选最短的路,肯定比你走远的路快啊!”

小周恍然大悟,深恨自己怎么没有早早想到这一点,不过亡羊补牢,为时未晚,立即决定效仿小美的做法。小周将店的位置标号为0,其他要送外卖的位置标号分别是1,2,3……然后又将各个标号之间的距离做了一张二维表A,其中A[0][i]代表从店家出发到第i个外卖点的距离,A[i][j](i!=0&&j!=0)表示第i个外卖点到第j个外卖点的距离。

小周每次都从店里出发,送完所有外卖之后,就从最后一个送完外卖的地点径直地回到店里,因为直接回去总是最近的,小周统计出来的表的确也是这样的。保证矩阵对称且主对角线上的元素都是0。

不过由于小周实在是太忙了,连计算最短路线的时间都没有,现在给你这张小周做好的表,请你帮小周确定一下最短的路线吧!

输入

第一行输入数据的组数T(1<=T<=50)。

对于每一组数据,第一行一个n(0 < n <= 9),代表要送的外卖数量,然后一个(n+1)*(n+1)的矩阵A,代表小周的统计出来距离表,0 <= A[i][j] <= 500。

输出

对于每组数据,输出送完所有外卖并回到店里的最短的距离

样例输入

2
0 52 
52 0
2
0 319
430 319
0 96 
430 96
 0

样例输出

104
845
TSP问题:
递归思想:
  从店家开始,尝试每种可能的送法,(试完后恢复局面)
  送完后把局面交给下一状态
  a[i][j]表示从i送到j

public class Problem_cid_1168_pid_10 {
	static int  min=5000;
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		 while (t-->0) {
			 int  num=cin.nextInt();
			 int a[][]=new  int[num+1][num+1];//距离
			 for (int i = 0; i < a.length; i++) {
				for (int j = 0; j < a.length; j++) {
					a[i][j]=cin.nextInt();
				}
			}
			 int currentsum=0;
			 boolean[][] b=new boolean[num+1][num+1];
			 for (int i = 0; i < b.length; i++)b[i][i]=true;
			 min=5000;
			 boolean  []hasdeal=new boolean[num+1];
			 f(num,a,currentsum,1, currentsum,b,0,hasdeal);
			 System.out.println(min);
		}
	}
	/**
	 *@param num:外卖份数
	*@param a:距离矩阵
	*@param currentsum:当前计算的距离总合   
	*@param y:下一份外卖在哪
	*@param dealnum:当前送出的外卖数
	*@param b:标记外卖是否已经送出
	*@param x:上一份外卖在哪
	 */
	private static void f(int num,int[][] a, int currentsum,int y,int dealnum,boolean [][]b,int x,boolean [] hasdeal) {
		 
		if (dealnum==num) {
			int ans=currentsum+a[y][0];
//		System.out.println("dealnum="+dealnum+"   currentsum="+currentsum+"   a["+x+"][0]="+a[x][0]+"   ans="+ans);
			min=Math.min(ans, min);
			return ;
		}
		if (currentsum>min)	return ;
		for (int i = 1; i <a[0].length ; i++) {//从这份外卖开始,尝试送出
			if (i!=x&&b[x][i]==false&&hasdeal[i]==false) {
			b[i][x]=b[x][i]=true;
			hasdeal[i]=true;
			f(num,a, currentsum+a[x][i],i, dealnum+1, b, i,hasdeal);
			hasdeal[i]=false;
			b[i][x]=b[x][i]=false;
			}
		}
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值