街区最短路径问题 java,街区最短路径问题分析和实现

时间限制:3000 ms | 内存限制:65535 KB

难度:4

描述 :

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

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

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

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

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

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

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

输入

第一行一个整数n<20,表示有n组测试数据,下面是n组数据;

每组第一行一个整数m<20,表示本组有m个住户,下面的m行每行有两个整数0

所在街区的坐标。

m行后是新一组的数据;

输出

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

样例输入

2

3

1 1

2 1

1 2

5

2 9

5 20

11 9

1 1

1 20

样例输出

2

44

============================即将用来揭示答案的华丽分割线========================================

解题思路:

1、距离和最小的邮局点一定设在某个居民点上,否则邮局到其他任何非居民点的距离总是会比最小距离多出来一段(非居民点到最近居民点的x+y距离)

2、因为距离只计算x轴和Y轴距离之和而不是斜对角线距离,所以可以把x轴距离和y轴距离分开分析计算最短距离,彼此一定不会影响

3、以x轴横向点到其他点最短距离为例:问题等价于在X轴有若干点中选取其中一点,使该点到其他点距离和最小

4、这个最短距离点一定是排在中间的那个点,比如有5个点,一定选择第3个点;如果有4个点,一定选择第2个点或者第3个点(可以证明选择这两个点任意一个,结果一定相同)

选择中间点的反证法证明:

假设选择非中间点,并认为该点到其他点的距离和最小,大家可以在X轴上画画图算算,一定还可以找到距离和比最小值还小一段距离的点(距离大小为假设最小点到中间点的距离),这和我们假设距离和最小条件矛盾,所以只能选中间点。

C++代码实现:

点击(此处)折叠或打开

#include

#include

#include

#include

#include

using namespace std;

int main(int argc, char** argv)

{

ifstream f_input("./input.txt");

string s_count;

if (!getline(f_input, s_count)) {

abort();

}

for (int i = 0; i < atoi(s_count.c_str()); i++) {

string s_num;

if(!getline(f_input, s_num)) {

abort();

}

// get all the x-coordinate and y-coordinate from the input.txt

vector xs, ys;

for (int j = 0; j < atoi(s_num.c_str()); j++) {

string s_line;

if (!getline(f_input, s_line)) {

abort();

}

string::size_type pos = s_line.find(" ");

int x = atoi(s_line.substr(0, pos).c_str());

int y = atoi(s_line.substr(pos+1, s_line.size()-1).c_str());

xs.push_back(x);

ys.push_back(y);

}

sort(xs.begin(), xs.end());

sort(ys.begin(), ys.end());

// calculate the minimium distance

int min = 0;

for (int c = 0; c < (atoi(s_num.c_str())+1)/2; c++) {

min += (xs[xs.size()-1-c] - xs[c]) + (ys[ys.size()-1-c] - ys[c]);

}

cout << "minimium distance:\t" << min << endl;

}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值