2019阿里校招测评——光明小学接力赛(Java)

合理宣泄下:太久没做题了,脑子锈了~然后拿到题,莫名大脑空白了10分钟,再接着看懂了题目,但就是不晓得怎么下手。所以就计划边写边想(至少把输入,主函数什么的敲进去),但是!!!不晓得是按错了Tab键还是什么,竟然交卷了,心塞的不行~~


题目:

*光明小学的小朋友们要举行一年一度的接力跑大赛了,但是小朋友们却遇到了一个难题:设计接力跑大赛的线路,你能帮助他们完成这项工作么?
 *光明小学可以抽象成一张有N个节点的图,每两点间都有一条道路相连。光明小学的每个班都有M个学生,所以你要为他们设计出一条恰好经过M条边的路径。
 *光明小学的小朋友们希望全盘考虑所有的因素,所以你需要把任意两点间经过M条边的最短路径的距离输出出来以供参考。
 *
 *你需要设计这样一个函数:
 *res[][] Solve( N, M, map[][]);
 *注意:map必然是N * N的二维数组,且map[i][j] == map[j][i],map[i][i] == 0,-1e8 <= map[i][j] <= 1e8。
 *(道路全部是无向边,无自环)2 <= N <= 100, 2 <= M <= 1e6。
 *
 *map数组表示了一张稠密图,其中任意两个不同节点i,j间都有一条边,边的长度为map[i][j]。N表示其中的节点数。
 *你要返回的数组也必然是一个N * N的二维数组,表示从i出发走到j,经过M条边的最短路径
 *你的路径中应考虑包含重复边的情况。


 *输入样例:
 

3
2
3 3
0 2 3
2 0 1
3 1 0

输出样例:

[[4, 4, 3],

[4, 2, 5],

[3, 5, 2]]


分析:该问题是无向图,题目自己都说明了。总共n个点,可以从任一点出发;每一个出发点,每次可以到达除了自身的所有点;最多可以走m次,(走表示从一个点到另一个点)。根据个人爱好,我喜欢把图画成树,因为每个点都可以作为出发点,那么就是n棵树,为了方便,自定义一个根节点连接到n棵树,这样就变成了1棵树。目的就是求,从根节点出发到叶子节点的所有可能路径,如果某些路径的起始点和终点都一样,那么我们只记录距离最短的那条。

依据题目给出的样例,可以根据下图理解上面的分析(左图为截取其他同学的分享(原题目内容),右图为树结构)

 


代码如下:(深度遍历树)对输入输出做了改动,具体看代码后贴出的输入,输出

import java.util.Arrays;
import java.util.Scanner;
public class DFS {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int[][] map = new int[n][n];
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				map[i][j] = in.nextInt();
			}
		}
		int[][] res = new int[n][n];//用来存储结果,初始化为最大值
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				res[i][j] = Integer.MAX_VALUE;
			}
		}
		int[] s = new int[m+2];
		s[0]=n;
		solve(n,m,1,n,s,map,res);
		for(int i=0;i<res.length;i++) {
			System.out.println(Arrays.toString(res[i]));
		}
	}
	/*
	 * 思路:把问题构造成一棵树,先深度遍历获取分支并存储
	 * 根据存储的分支,计算路径长度,做出处理
	 */
	public static void solve(int n,int m,int t,int root,int[] s,int[][] map,int[][] res){
		//输入:t:表示从第几层开始遍历,root:表示当前所在结点,s:用来存遍历得到的分支
		if(t==(m+2)) {
			int sum=0;
			for(int j=1;j<s.length-1;j++) {
				sum += map[s[j]][s[j+1]];
			}
			if(sum<res[s[1]][s[m+1]])
				res[s[1]][s[m+1]] = sum;
			//System.out.println(Arrays.toString(s));//输出从根到叶的一条支路
		}
		else {
			int[] arr = find(n,root);
			for(int i=0;i<arr.length;i++) {
				s[t] = arr[i];
				solve(n,m,t+1,arr[i],s,map,res);
			}
		}
	}
	
	public static int[] find(int n,int root) {//根据当前结点获取它能到达的所有子树的根
		int[] arr;
		if(root==n) {
			arr = new int[n];
			for(int i=0;i<n;i++) {
				arr[i] = i;
			}
		}
		else {
			arr = new int[n-1];
			int t = 0;
			for(int i=0;i<n;i++) {
				if(i==root) continue;
				arr[t] = i;
				t++;
			}
		}
		return arr;
	}
}
/*
输入:
3
2
0 2 3
2 0 1
3 1 0
输出:
[4, 4, 3]
[4, 2, 5]
[3, 5, 2]
*/

参考:图片来源于

http://www.cnblogs.com/Oscar67/p/9366689.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值