街区最短路径问题

描述
一个街区有很多住户,街区的街道只能为东西、南北两种方向。

住户只可以沿着街道行走。

各个街道之间的间隔相等。

用(x,y)来表示住户坐在的街区。

例如(4,20),表示用户在东西方向第4个街道,南北方向第20个街道。

现在要建一个邮局,使得各个住户到邮局的距离之和最少。

求现在这个邮局应该建在那个地方使得所有住户距离之和最小;

输入
第一行一个整数n<20,表示有n组测试数据,下面是n组数据;
每组第一行一个整数m<20,表示本组有m个住户,下面的m行每行有两个整数0<x,y<100,表示某个用户所在街区的坐标。
m行后是新一组的数据;
输出

每组数据输出到邮局最小的距离和,回车结束;

Java代码实现:

import java.util.*;
/**
 * 街区最短路径问题
 * @author sdu20
 *
 */
public class MinStreet {
	
	private static int disMin(int[][] points){
		
		if(points.length==1){
			return 0;
		}
			
		int minx = points[0][0];
		int miny = points[0][1];
		int maxx = points[0][0];
		int maxy = points[0][1];
		for(int i = 1;i<points.length;i++){
			if(minx>points[i][0])
				minx = points[i][0];
			else if(maxx<points[i][0])
				maxx = points[i][0];
			
			if(miny>points[i][1])
				miny = points[i][1];
			else if(maxy<points[i][1])
				maxy = points[i][1];
		}
		
		int minsum = 0;
		for(int k = 0;k<points.length;k++)
			minsum += Math.abs(maxx-points[k][0]) + Math.abs(maxy-points[k][1]);
		for(int i = minx;i < maxx;i++){
			for(int j = miny;j < maxy;j++){
				int sum = 0;
				for(int k = 0;k<points.length;k++){
					sum += Math.abs(i-points[k][0]) + Math.abs(j-points[k][1]);
				}
				if(minsum>sum)
					minsum = sum;				
			}
		}
		
		return minsum;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

//		int[][] nums = {{2,9},{5,20},{11,9},{1,1},{1,20}};
//		System.out.println(disMin(nums));
		Scanner in = new Scanner(System.in);
		int arraysnum = in.nextInt();
		int[] results = new int[arraysnum];
		
		for(int i = 0;i<arraysnum;i++){
			int alen = in.nextInt();
			int[][] points = new int[alen][2];
			for(int j = 0;j<alen;j++){
				points[j][0] = in.nextInt();
				points[j][1] = in.nextInt();
			}
			results[i] = disMin(points);
		}
		
		for(int i = 0;i<arraysnum;i++){
			System.out.println(results[i]);
		}
		
	}

}

运行结果截图:


把main方法和dismin方法中的循环合并的话时间应该会减少不少。但是我觉着这个问题应该有另一种方法可以解出,应该是类似于用一个式子直接计算出来的那种,但是我现在还没有想出来。

==================分割线=========================

另外一种更加简短且效率更高的方法:

import java.util.*;
/**
 * 街区最短路径问题的另一种解法
 * @author sdu20
 *
 */
public class MinStreet2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner in = new Scanner(System.in);
		int arraysnum = in.nextInt();
		int[] results = new int[arraysnum];
		
		for(int i = 0;i<arraysnum;i++){
			int arraylength = in.nextInt();
			int[] x = new int[arraylength];
			int[] y = new int[arraylength];
			for(int j = 0;j<arraylength;j++){
				x[j] = in.nextInt();
				y[j] = in.nextInt();				
			}
			Arrays.sort(x);
			Arrays.sort(y);
			int sum = 0;
			for(int j = 0;j<arraylength/2;j++){
				sum += x[arraylength-1-j]-x[j] + y[arraylength-1-j]-y[j];				
			}
			results[i] = sum;
		}
		
		for(int i = 0;i<arraysnum;i++)
			System.out.println(results[i]);
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值