HDU 4311 Meeting point-1(dp)

202 篇文章 1 订阅

Description

给出二维平面的 n n 个点的坐标,定义两点之间距离为曼哈顿距离,要求从这n个点中选一个点使得其他点到该点距离之和最小

Input

第一行一整数 T T 表示用例组数,每组用例首先输入一整数n表示点数,之后 n n 行每行输入两个整数xi,yi表示第 i i 个点的横纵坐标(1T10,1n105,109xi,yi109)

Output

输出最小距离和

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

Solution

先把所有点按横坐标排序得到 n n 个不减的横坐标,记sumi=j=1n|xixj|

sumi+1=j=1i1(xi+1xj)+xi+1xi+j=i+1n(xjxi+1)=sumi+(2in)(xi+1xi) s u m i + 1 = ∑ j = 1 i − 1 ( x i + 1 − x j ) + x i + 1 − x i + ∑ j = i + 1 n ( x j − x i + 1 ) = s u m i + ( 2 i − n ) ⋅ ( x i + 1 − x i )

以此 O(n) O ( n ) 即可得到 sum s u m 序列,即一个点被选中后其横坐标对答案的贡献,同理按纵坐标排序求出每个点纵坐标对答案的贡献,两者相加取最小值即为答案

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100005;
struct node
{
    int x,y,id;
}a[maxn];
ll sum[maxn],ans; 
bool cmpx(node a,node b)
{
    return a.x<b.x;
}
bool cmpy(node a,node b)
{
    return a.y<b.y;
}
int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&a[i].x,&a[i].y);
            a[i].id=i;
        }
        sort(a+1,a+n+1,cmpx);
        ll temp=0;
        for(int i=2;i<=n;i++)temp+=a[i].x-a[1].x;
        sum[a[1].id]=temp;
        for(int i=2;i<=n;i++)
        {
            temp+=(ll)(2*(i-1)-n)*(a[i].x-a[i-1].x);
            sum[a[i].id]=temp;
        }
        sort(a+1,a+n+1,cmpy);
        temp=0;
        for(int i=2;i<=n;i++)temp+=a[i].y-a[1].y;
        sum[a[1].id]+=temp;
        for(int i=2;i<=n;i++)
        {
            temp+=(ll)(2*(i-1)-n)*(a[i].y-a[i-1].y);
            sum[a[i].id]+=temp;
        }
        ll ans=sum[1];
        for(int i=2;i<=n;i++)ans=min(ans,sum[i]);
        printf("%lld\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值