ACM_07

描述

一个街区有很多住户,街区的街道只能为东西、南北两种方向。住户只可以沿着街道行走。各个街道之间的间隔相等。用(x,y)来表示住户坐在的街区。例如(4,20),表示用户在东西方向第4个街道,南北方向第20个街道。现在要建一个邮局,使得各个住户到邮局的距离之和最少。求现在这个邮局应该建在那个地方使得所有住户距离之和最小;

输入

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

输出:

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

暴力破解:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int main(int argc, char** argv) {

    int nNums = 0;
    scanf("%d", &nNums);getchar();
    int pointArray[20][2];

    while (nNums--) {
        int nPoints = 0;
        scanf("%d", &nPoints); getchar();

        int nMaxX = 0,nMaxY = 0;
        for (int i = 0; i < nPoints; ++i) {
            scanf("%d %d", &pointArray[i][0], &pointArray[i][1]);
            if (nMaxX < pointArray[i][0])nMaxX = pointArray[i][0];
            if (nMaxY < pointArray[i][1]) nMaxY = pointArray[i][1];
        }
        int Smin = 1000000;
        int TempSmin = 0;
        //暴力遍历破解
        for (int i = 0; i < nMaxX + 1; ++i) {
            for (int j = 0; j < nMaxY + 1; ++j){
                for(int k = 0; k < nPoints; ++k)
                    TempSmin += abs(pointArray[k][0] - i) + abs(pointArray[k][1] - j);

            if (Smin > TempSmin)
                Smin = TempSmin;
            TempSmin = 0;
            }
        }
        printf("%d\n", Smin);
    }
    return 0;
}

这里写图片描述

出租车几何或曼哈顿距离(Manhattan Distance)是由十九世纪的赫尔曼·闵可夫斯基所创词汇 ,是种使用在几何度量空间的几何学用语,用以标明两个点在标准坐标系上的绝对轴距总和。图中红线代表曼哈顿距离,绿色代表欧氏距离,也就是直线距离,而蓝色和黄色代表等价的曼哈顿距离。曼哈顿距离——两点在南北方向上的距离加上在东西方向上的距离,即d(i,j)=|xi-xj|+|yi-yj|。对于一个具有正南正北、正东正西方向规则布局的城镇街道,从一点到达另一点的距离正是在南北方向上旅行的距离加上在东西方向上旅行的距离,因此,曼哈顿距离又称为出租车距离。曼哈顿距离不是距离不变量,当坐标轴变动时,点间的距离就会不同。曼哈顿距离示意图在早期的计算机图形学中,屏幕是由像素构成,是整数,点的坐标也一般是整数,原因是浮点运算很昂贵,很慢而且有误差,如果直接使用AB的欧氏距离(欧几里德距离:在二维和三维空间中的欧氏距离的就是两点之间的距离),则必须要进行浮点运算,如果使用AC和CB,则只要计算加减法即可,这就大大提高了运算速度,而且不管累计运算多少次,都不会有误差。

#include <iostream>
#include <algorithm>
using namespace std;

int main(int argc, char** argv) {

    int nNums = 0;
        std::cin>>nNums;
    int pointX[20],pointY[20];

    while (nNums--) {
        int nPoints = 0;
            std::cin >> nPoints;
        for (int i = 0; i < nPoints; ++i)
            std::cin>>pointX[i]>>pointY[i];
        //排序
        sort(pointX, pointX + nPoints);
        sort(pointY, pointY + nPoints);
        //获取中位点
        int X, Y;
        if (nPoints % 2 != 0) {
            X = pointX[nPoints / 2 ];
            Y = pointY[nPoints / 2 ];
        }else {
            X = (pointX[nPoints / 2 - 1] + pointX[nPoints / 2]) / 2;
            Y = (pointY[nPoints / 2 - 1] + pointY[nPoints / 2]) / 2;
        }
        //计算最小距离
        int Smin = 0;
        for (int i = 0; i < nPoints; ++i) {
            Smin += abs(X - pointX[i]) + abs(Y - pointY[i]);
        }
        std::cout<<Smin<<std::endl;
    }
    return 0;
}

我查看了一下标程,标程里面针对中位点计算最短距离进行了优化。减少了运行次数。去除了中位点本身的位置计算。

#include<iostream>
#include<algorithm>
using namespace std;
int x[30],y[30],n,m,i;;
int main()
{
    cin>>n;
    while(n--)
    {
        cin>>m;
        for(i=0;i<m;i++)
            cin>>x[i]>>y[i];
        //排序
        sort(x,x+m);
        sort(y,y+m);
        int sum=0;
        //除去中位点本身,其他点到中位点的距离和
        for(i=0;i<m/2;i++)
            sum+=x[m-1-i]-x[i]+y[m-1-i]-y[i];
        cout<<sum<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值