2387(数学曼哈顿距离)

题意:给出n个点及其坐标,求一点到其它点曼哈顿距离总和最小值以及解的个数。

两点曼哈顿距离公式:d=|x1−x2|+|y1−y2|,由于两点曼哈顿距离的特性,单独求 x 与单独求 y 互不影响

因此,题目即为求 |x−x1|+|x−x2|+…+|x−xn| 的最小值,求 |y−y1|+|y−y2|+…+|y−yn| 的最小值,直接求两者中位数即可。

接对 x、y 各自进行排序比较:

    1)当n为奇数时,取( x[n/2+1],y[n/2+1] )

  若该点为给出点,枚举它的上下左右四个方向上的点能求的最小的 d,然后统计当且仅当这4个点的方案数;

  若该点不为给出点,则直接记录最小距离,方案数为1。

    2)当n为偶数时,取( x[n/2],y[n/2] )和( x[n/2+1],y[n/2+1] )

        由曼哈顿距离的特性知:共有( x[n/2+1]−x[n/2]+1)*( y[n/2+1]−y[n/2]+1)个点构成一个方块,且它们到给定的n个点(包括在方块内的点)的曼哈顿距离和d(所需求的距离)相等。由于题目说cows never graze in spots that are horizontally or vertically adjacent,(牛不会水平或者垂直相邻)那么被占满的情况就只有n是奇数的情况。因此枚举每个点是否为给定的点,求一次最小距离,再先让方案数为点的个数,每次更新减小方案数即可。

补充一个样例:

input:

4

1 1

2 2

3 3

4 4

output:

8 2

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<set>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 10001
#define MOD 123
#define E 1e-6
using namespace std;
int dx[4]= {0,1,0,-1};
int dy[4]= {1,0,-1,0};
struct Node
{
    int x;
    int y;
} a[N];
int x[N],y[N];
int minn,plan;
int main()
{
 
    int n;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d%d",&a[i].x,&a[i].y);
        x[i]=a[i].x;
        y[i]=a[i].y;
    }
 
    sort(x+1,x+n+1);
    sort(y+1,y+n+1);
 
    if(n%2)
    {
        int temp=(n/2)+1;
        for(int i=1; i<=n; i++)
        {
            if(a[i].x==x[temp]&&a[i].y==y[temp])
            {
                int Min=INF;
                for(int l=0; l<4; l++)
                {
                    int xx=x[temp]+dx[l];
                    int yy=y[temp]+dy[l];
                    int sum=0;
                    for(i=1; i<=n; i++)
                        sum+=abs(a[i].x-xx)+abs(a[i].y-yy);
                    if(sum<Min)
                    {
                        Min=sum;
                        plan=1;
                    }
                    else if (sum==Min)
                        plan++;
                }
                printf("%d %d\n",Min,plan);
                return 0;
            }
            else
            {
                minn+=abs(a[i].x-x[temp])+abs(a[i].y-y[temp]);
                plan=1;
            }
        }
        printf("%d %d\n",minn,plan);
    }
    else
    {
        int temp1=n/2,temp2=n/2+1;
        plan=(x[temp2]-x[temp1]+1)*(y[temp2]-y[temp1]+1);
        for(int i=1; i<=n; i++)
        {
            minn+=abs(a[i].x-x[temp1])+abs(a[i].y-y[temp1]);
            int x0=a[i].x,y0=a[i].y;
            if (x[temp1]<=x0&&x0<=x[temp2]&&y[temp1]<=y0&&y0<=y[temp2])
                plan--;
        }
        printf("%d %d\n",minn,plan);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40061421/article/details/86583106