NYOJ-7街区最短问题

街区最短路径问题

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

描述

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

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

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

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

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

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

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

输入

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

输出

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

样例输入

2
3
1 1
2 1
1 2
5
2 9 
5 20
11 9
1 1
1 20

样例输出

2
44

由于测试数据比较弱,刚开始直接暴力也能过。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
typedef struct node
{
    int x,y;
}point;
const int inf = 0x3f3f3f3f;
const int maxn=105;
int m;
vector<point> ve;
void init()
{
    ve.clear();
    cin>>m;
    int x,y;
    for(int i=0;i<m;i++)
    {
        cin>>x>>y;
        point temp={y,x};
        ve.push_back(temp);
    }
}
int solve()
{
    int ans=inf,sum;
    for(int i=1;i<100;i++)
    {
        for(int j=1;j<100;j++)
        {
            sum=0;
            for(int k=0;k<ve.size();k++)
            {
                sum+=(abs(ve[k].x-i)+abs(ve[k].y-j));
            }
            ans=min(ans,sum);
        }
    }
    return ans;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        init();
        cout<<solve()<<endl;
    }
    return 0;
}

法二:数学:在一维的数轴上,一点x到数轴上多点的距离和最小 = a[max]-a[0]+a[max-1]-a[0+1]+….直到max-n<=0+n;

/*
    此题为数学类问题,目的是为了找一个点,使这个点到每条边的距离最短,
    本题中,可以用一个简单地思路,分别把坐标x,y,分开,
    那么这道题就简化为:在给定的m个点中,求每个点到x的距离的和的最小值,
    即:min{∑|xi-x|},故本题的结果应该是:距离=min{∑|xi-x|}+min{∑|yi-y|}。

    为了是问题更简化,可以先将x坐标y坐标分别按升序排序,然后用最后一个数减去第一个,
    倒数第二个减去正数第二个......以此类推。(这样做的原因是,想要找出一点,
    使该点到两个端点的距离的和最小,则这个点必落在两个端点之间。)
*/
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int x[20],y[20];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int m;
        cin>>m;
        for(int i=0;i<m;i++)
            cin>>x[i]>>y[i];
        sort(x,x+m);
        sort(y,y+m);
        int ans=0;
        for(int i=m-1,j=0;i>j;i--,j++) //到 x点和的最短距离。
            ans+=(x[i]-x[j]+y[i]-y[j]);
        cout<<ans<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值