CF1496C-Diamond Miner

C - Diamond Miner

题目描述

n n n 个矿工在 y y y 轴上, n n n 个钻石矿在 x x x 轴上,原点处(坐标 ( 0 , 0 ) (0,0) (0,0) )什么也没有,每个矿工要负责拿一块钻石矿,每个钻石矿恰好被一个矿工采走。采一个钻石矿的代价为矿工与钻石矿间的直线距离。求总代价的最小值。

数据范围与提示

共有 t t t 组数据;

1 ≤ t ≤ 10 , 1 ≤ n ≤ 1 0 5 , − 1 0 8 ≤ x , y ≤ 1 0 8 1\le t\le 10,1\le n\le 10^5,-10^8\le x,y\le 10^8 1t101n105108x,y108 ;

n n n 的总和不超过 1 0 5 10^5 105

思路

由于一个矿工和一个钻石矿的距离为 y 2 + x 2 \sqrt{y^2+x^2} y2+x2 ,所以实际上和坐标正负无关,所以先把所有坐标都取绝对值。

然后通过画图我们可以知道,交叉的线一定不优:

在这里插入图片描述

所以只需要把坐标从小到大排序然后一一对应即可。复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn)

这题应该没人用非结论做法吧

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#define ll long long
#define MAXN 100005
#define uns unsigned
using namespace std;
inline ll read(){
	ll x=0;bool f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
	while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
	return f?x:-x;
}
int n;
vector<double>a,b;
inline double dis(double c,double d){
	return sqrt(c*c+d*d);
}
signed main()
{
	for(int T=read();T--;){
		n=read();
		a.clear(),b.clear();
		for(int i=1;i<=(n<<1);i++){
			double x=read(),y=read();
			if(x<0)x=-x;if(y<0)y=-y;
			if(x==0)a.push_back(y);
			else b.push_back(x);
		}
		sort(a.begin(),a.end());
		sort(b.begin(),b.end());
		double ans=0;
		for(int i=0;i<n;i++)ans+=dis(a[i],b[i]);
		printf("%.15f\n",ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值