曼哈顿距离与切比雪夫距离的转化 以51nod 首都为例

曼哈顿距离与切比雪夫距离的转化  

                                               以51nod 首都为例

1.曼哈顿距离与切比雪夫距离

曼哈顿距离——两点在南北方向上的距离加上在东西方向上的距离,即d(i,j)=|xi-xj|+|yi-yj|。

曼哈顿距离与切比雪夫距离的转化 以51nod 首都为例_第1张图片

切比雪夫距离是向量空间中的一种度量,二个点之间的距离定义为其各座标数值差绝对值的最大值。以(x1,y1)和(x2,y2)二点为例,其切比雪夫距离为max(|x2-x1|,|y2-y1|)。

曼哈顿距离与切比雪夫距离的转化 以51nod 首都为例_第2张图片

2.曼哈顿距离与切比雪夫距离的转化

大佬的讲解

曼哈顿距离 与 切比雪夫距离 之间会不会有联系呢?

设 A(x1,y1),B(x2,y2)

A,B 两点的曼哈顿距离为:|x1-x2|+|y1-y2|

                                         =max{x1-x2+y1-y2,x1-x2+y2-y1,x2-x1+y1-y2,x2-x1+y2-y1}

                                         =max{|(x1+y1)-(x2+y2)|,|(x1-y1)-(x2-y2)|}

易知A,B两点的曼哈顿距离即为(x+y,x-y)的切比雪夫距离;

同理,A,B两点的切比雪夫距离为:max{|x1-x2|,|y1-y2|}

                                                         =max{x1-x2,x2-x1,y1-y2,y2-y1}

                                                         =|(x1+y1)/2-(x2+y2)/2|+|(x1-y1)/2-(x2-y2)/2|

易知A,B两点的切比雪夫距离即为((x+y)/2,(x-y)/2))的曼哈顿距离;

3.51nod 首都

3.1链接

3.2题意

求在二维坐标系中到所有点切比雪夫距离之和最小的点的数量和值;

3.3分析

在求距离之和上,切比雪夫距离并不好求,但是这题转化为曼哈顿距离相对来说就简单一些了。

将所有点转化为求曼哈顿距离的点,二维相对比较难求和,但本题可以分开在x上求和和在y上求和

分别对x排序和对y排序,选取中间区域的点,即为最小距离

需要注意的是由于是转化为曼哈顿距离的点,所以求点的数量需要转化回切比雪夫距离上的点

易知对于x+y和x-y可以得到唯一解,但x+y和x-y必定同偶或者同奇,否则无解。

具体分析见代码

3.4代码

#include 
#include 
using namespace std;
#pragma warning (disable:4996)
typedef long long int LL;
const int maxn = 100005;
const LL inf = 1e18;
#define abs(x) ((x)<0?-(x):(x))
int x[maxn], y[maxn];
int main() {
	int n; cin>>n;
	register int dx, dy;
	for (int i = 1; i <= n; i++) {
		cin>>dx>>dy;
		x[i] = dx + dy;		//转化为曼哈顿距离
		y[i] = dx - dy;
	}
	sort(x + 1, x + 1 + n);		//按x排序
	sort(y + 1, y + 1 + n);		//按y排序
	LL ans = 0, cnt = 0;	//距离和点数
	if (n & 1) {			//奇数个点
		int mid = (n + 1) >> 1,			
			left = x[mid], right = y[mid];
		if ((right - left) & 1)			//如果同奇偶性则无解
			cnt = 0;
		else
			cnt = 1;
	}
	else {
		int mid = n >> 1;
		LL	l1 = x[mid], r1 = x[mid + 1],		//预处理
			l2 = y[mid], r2 = y[mid + 1],
			len1 = abs(l1 - r1) + 1,
			len2 = abs(l2 - r2) + 1,
			leng1 = len1 >> 1,
			leng2 = len2 >> 1;
		if (len1 & 1) {				//x轴奇数个点
			if (len2 & 1) {			//y轴奇数个点
				if ((l1 - l2) & 1) {		//两轴占大多数的元素奇偶性不同
					cnt = leng1 * (leng2 + 1) + (leng1 + 1) * leng2;
				}
				else {		//两轴占大多数的元素奇偶性相同
					cnt = (leng1 + 1) * (leng2 + 1) + leng1 * leng2;
				}
			}
			else {				//y轴偶数个点
				cnt = leng1 * leng2 + (leng1 + 1) * leng2;
			}
		}
		else {				//x轴偶数个点
			if (len2 & 1) {				//y轴奇数个点
				cnt = leng1 * leng2 + leng1 * (leng2 + 1);
			}
			else {						//y轴偶数个点
				cnt = (leng1 * leng2) + (leng1 * leng2);
			}
		}
	}
	int mid = (n + 1) >> 1;
	if (!cnt) {		//点数为0,易知答案为距离最近的点
		LL ex[4] = { -1,0,1,0 },
			ey[4] = { 0,-1,0,1 };		//向四个方向搜索
		ans = inf;
		for (int i = 0; i < 4; i++) {
			LL _X = x[mid] + ex[i],
				_Y = y[mid] + ey[i],
				sum = 0;
			for (int i = 1; i <= n; i++)
				sum += abs(_X - x[i]);
			for (int i = 1; i <= n; i++)
				sum += abs(_Y - y[i]);
			if (sum < ans)			//若为最小值,更新
				cnt = 1, ans = sum;
			else if (sum == ans)
				cnt++;
		}
		printf("%lld\n%lld\n", ans >> 1, cnt);
	}
	else {
		LL m = x[mid];			//x方向的曼哈顿距离
		for (int i = 1; i < mid; i++)
			ans += m - x[i];
		for (int i = mid + 1; i <= n; i++)
			ans += x[i] - m;
		m = y[mid];				//y方向的曼哈顿距离
		for (int i = 1; i < mid; i++)
			ans += m - y[i];
		for (int i = mid + 1; i <= n; i++)
			ans += y[i] - m;
		printf("%lld\n%lld\n", ans >> 1, cnt);
	}
}

你可能感兴趣的:(数论)