蓝桥杯 第十二届 试题E:路径 (java)

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图 中的最短路径。

小蓝的图由 2021 个结点组成,依次编号 1 至 2021。

对于两个不同的结点 a, b,如果 a 和 b 的差的绝对值大于 21,则两个结点 之间没有边相连;如果 a 和 b 的差的绝对值小于等于 21,则两个点之间有一条 长度为 a 和 b 的最小公倍数的无向边相连。

例如:结点 1 和结点 23 之间没有边相连;结点 3 和结点 24 之间有一条无 向边,长度为 24;结点 15 和结点 25 之间有一条无向边,长度为 75。

请计算,结点 1 和结点 2021 之间的最短路径长度是多少。

提示:建议使用计算机编程解决问题。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

代码:

public class TestDemo1 {
	public static int INF = Integer.MAX_VALUE/2;
	
	public static void main(String[] args) {
		//存放图的二维矩阵
		int[][] board = new int[2100][2100];
		//标记每个节点的访问状态
		boolean[] flg = new boolean[2100];
		//保存一个点到其他点的最短距离
		int[] dist = new int[2100];
		
		createBoard(board);     //对board和dist进行初始化
		initDist(dist);
		
		dijkstra(1,board,flg,dist);    //传一个1,表示求编号 1 的点到 其它点的最短距离
		
		System.out.println(dist[2021]);//dist数组中所保存的就是 原点到所有点的最短距离
	}

	/**
	 * dijkstra
	 * @param base    原点
	 * @param board   存放着图的信息
	 * @param flg     存放每个节点的状态(是否被访问过)
	 * @param dist    存放原点到每个点的最短距离
	 */
	private static void dijkstra(int base, int[][] board, boolean[] flg, int[] dist) {
		//将原点到自生的距离初始化为 0;
		dist[base] = 0;
		//遍历除原点的其它所有的点
		for(int i = 2; i <= 2021; i++) {
			
			int ret = -1;   //记录 : 中间点的下标
			
			//这个for循环用来寻找当前节点到所用节点中,距离最短的那个点(已访问的除外)
			for(int j = 1; j <= 2021 ; j++) {
				//查看是否访问过,并且是不是第一次进入循环
				if(flg[j] == false && (ret == -1 || dist[j] < dist[ret])) {
					//记录下标
					ret = j;
				}
			}
			//更改当前寻找到的最短距离的点的状态
			flg[ret] = true;
			
			//这个循环用来更新 dist 中的最短距离(与所有的点都进行判断一下,找出最小距离)
			for(int j = 1; j <= 2021; j++) {
				//找到的最小距离 更新 到 dist 中
				dist[j] = Math.min(dist[j], dist[ret] + board[ret][j]);
			}
		}
	}

	/**
	  * 对 dist 数组进行初始化
	 * @param dist
	 */
	private static void initDist(int[] dist) {
		for(int i = 0; i < dist.length; i++) {
			dist[i] = INF;
		}
	}
	
	
	/**
	  * 初始化图
	 * @param board
	 */
	public static void createBoard(int[][] board) {
		for(int i = 1; i <= 2021; i++) {
			for(int j = 1; j <= 2021; j++) {			
				if(i == j) {
					board[i][j] = 0;
				}else if(Math.abs(i-j) > 21) {
					board[i][j] = INF;
				}else {
					board[i][j] = lcm(i,j);
				}
			}
		}
	}
		
	/**
	  * 求出两个整数的最大公约数
	 * @param a
	 * @param b
	 * @return
	 */
	public static int gcd(int a,int b) {
		if(b == 0) {
			return a;
		}
		return gcd(b,a%b);
	}
	
	/**
	  * 求出两个数的最小公倍数
	 * @param a
	 * @param b
	 * @return
	 */
	public static int lcm(int a,int b) {
		return a*b/gcd(a,b);
	}
}

结果: 10266837

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值