hdu_4311_Meeting point-1(曼哈顿距离)及其拓展

news/2024/11/15 8:16:46/

hdu_4311_Meeting point-1(曼哈顿距离)及其拓展

题目链接

题目描述

给定n个点,找出其中一个点,使得其他点到这个点的曼哈顿距离和最小,求这个最小距离和。

Sample Input

4
6
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2
6
0 0
2 0
-5 -2
2 -2
-1 2
4 0
5
-5 1
-1 3
3 1
3 -1
1 -1
10
-1 -1
-3 2
-4 4
5 2
5 -4
3 -1
4 3
-1 -2
3 4
-2 2

Sample Output

26
20
20
56

解题思路

曼哈顿距离:两个点的横纵坐标的差的绝对值之和;
d i c = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ dic=|x_1-x_2|+|y_1-y_2| dic=x1x2+y1y2
题目要求计算的结果为
d i c = ∑ i = 1 n ∣ x i − x ∣ + ∑ i = 1 n ∣ y i − y ∣ dic=\sum_{i=1}^n{|x_i-x|}+\sum_{i=1}^n{|y_i-y|} dic=i=1nxix+i=1nyiy
暴力解法就是,遍历所有点,计算其到其他所有点的曼哈顿距离和,记录最小值,时间复杂度是O( n 2 n^2 n2);
优化过程:预处理两个数组sum_x[n],sum_y[n];
sum_x[i]表示到序号i为止的点的横坐标的和。
sum_y[i]表示到序号i为止的点的纵坐标的和。
将所有点按x排序后:
s u m x = ∑ i = 1 n ∣ x i − x ∣ = ( i − 1 ) ∗ x [ i ] − s u m x [ i − 1 ] + s u m x [ n ] − s u m x [ i ] − ( n − i ) ∗ x [ i ] ; sum_x=\sum_{i=1}^n{|x_i-x|} =(i - 1)*x[i] - sum_x[i - 1] + sum_x[n] - sum_x[i] - (n - i)*x[i]; sumx=i=1nxix=(i1)x[i]sumx[i1]+sumx[n]sumx[i](ni)x[i];
将所有点按y排序后:
s u m y = ∑ i = 1 n ∣ y i − y ∣ = ( i − 1 ) ∗ y [ i ] − s u m y [ i − 1 ] + s u m y [ n ] − s u m y [ i ] − ( n − i ) ∗ y [ i ] ; sum_y=\sum_{i=1}^n{|y_i-y|} =(i - 1)*y[i] - sum_y[i - 1] + sum_y[n] - sum_y[i] - (n - i)*y[i]; sumy=i=1nyiy=(i1)y[i]sumy[i1]+sumy[n]sumy[i](ni)y[i];
时间复杂度为O(nlog(n));

AC代码

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
const int maxn=100005;
struct note
{int x,y,id;
} a[maxn];
int x[maxn],y[maxn],n;
LL numx[maxn],numy[maxn];bool cmp1(note a,note b)
{return a.x<b.x;
}bool cmp2(note a,note b)
{return a.y<b.y;
}int main()
{int T;scanf("%d",&T);while(T--){scanf("%d",&n);LL sumx=0,sumy=0;for(int i=1; i<=n; i++){scanf("%d%d",&x[i],&y[i]);a[i].x=x[i];a[i].y=y[i];a[i].id=i;sumx+=x[i];sumy+=y[i];}sort(a+1,a+n+1,cmp1);LL ans=0;for(int i=1; i<=n; i++){ans+=a[i].x;int j=a[i].id;numx[j]=(LL)x[j]*(2*i-n)+sumx-2*ans;}sort(a+1,a+1+n,cmp2);ans=0;for(int i=1; i<=n; i++){ans+=a[i].y;int j=a[i].id;numy[j]=(LL)y[j]*(2*i-n)+sumy-2*ans;}ans=numy[1]+numx[1];for(int k=2; k<=n; k++)ans=min(ans,numx[k]+numy[k]);printf("%I64d\n",ans);}return 0;
}

####扩展
给定n个点的坐标,求出一个点(不一定是n个点之一),使得其到其他所有点的曼哈顿距离和最小;
易知,要求的点的x值必定是n个点中某一个点的x值,y值必定是n个点中某一个点的y值,但未必是同一个点的x值和y值;求x和y的过程跟上面一题一样。


http://www.ppmy.cn/news/554511.html

相关文章

jzoj4311 统一天下

Description Input Output Sample Input 4 4 1 3 2 1 4 3 4 3 4 1 1 2 Sample Output 68 Data Constraint 算法讨论 问题的关键是如何求出两棵树的重心&#xff0c;那就是f[i]&#xff0c;即所有点到点i的距离&#xff0c;首先dfs一次求出f[1]和z[i](i的子树的大小)…

HDU 4311 Meeting point-1

2016暑期集训1-A HDU 4311 Meeting point-1 预处理&#xff0c;前缀和&#xff0c;递推计算&#xff0c;距离去绝对值技巧 传送门&#xff1a;HustOJ 传送门&#xff1a;HDU 题意 平面上有n个点&#xff0c;定义两点间的距离D为 |x1-x2| |y1-y2|。从n个点中找到一点&#x…

P4311 士兵占领 上下界费用流 or 最大流

题目描述 有一个M * N的棋盘&#xff0c;有的格子是障碍。现在你要选择一些格子来放置一些士兵&#xff0c;一个格子里最多可以放置一个士兵&#xff0c;障碍格里不能放置士兵。我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵。现在你的…

【线段树分治】[BZOJ4311]向量

题目描述 Description 你要维护一个向量集合&#xff0c;支持以下操作&#xff1a; 1.插入一个向量(x,y) 2.删除插入的第i个向量 3.查询当前集合与(x,y)点积的最大值是多少。如果当前是空集输出0 Input 第一行输入一个整数n&#xff0c;表示操作个数 接下来n行&#xff0c;每行…

bzoj4311向量(线段树分治+斜率优化)

第二道线段树分治。 首先设当前向量是(x,y)&#xff0c;剩余有两个不同的向量(u1,v1)(u2,v2)&#xff0c;假设u1>u2&#xff0c;则移项可得&#xff0c;若(u1,v1)优于(u2,v2)&#xff0c;则-x/y>(v1-v2)/(u1-u2)&#xff0c;然后维护上凸壳后进行三分即可&#xff0c;复杂…

[BZOJ1458][luogu 4311] 士兵占领 网络流建模

那天听 dyx d y x 讲课还是懵逼了半天 结果发现自己根本没怎么做过网络流&#xff0c; 板子都不会打了 qwq q w q 还是一点点从他的课件里刷起来把 这个题我们首先可以换种思维方法 在有限制的情况下放最少的士兵 可以把所有士兵放上去之后 在有限制的情况下删最多的士兵 这…

洛谷4311 士兵占领(最大流)

传送门 【题目分析】 又是一道魔性的网络流。。。。 考虑会导致“JIONG!”的情况&#xff0c;无非就是当前这一行&#xff08;列&#xff09;需要的士兵个数<可放置士兵个数&#xff0c;所以在读障碍的时候记一下影响的行和列&#xff0c;然后与每行每列最少需要的士兵进…

【BZOJ4311】向量(线段树分治,斜率优化)

【BZOJ4311】向量&#xff08;线段树分治&#xff0c;斜率优化&#xff09; 题面 BZOJ 题解 先考虑对于给定的向量集&#xff0c;如何求解和当前向量的最大内积。 设当前向量\((x,y)\)&#xff0c;有两个不同的向量\((u1,v1),(u2,v2)\)&#xff0c;并且\(u1>u2\) 假设第一个…