题目大意:
给出平面2n点,有两个玩家游戏。每个回合,玩家A可以取走一个点,然后玩家B取走一个。经过n个回合没有点了,结束比赛。一个玩家的得分是他所取走的所有两两之间的欧几里得距离的和,得分最高者获胜。A和B都是聪明人,求两者分数之差为多少。
思路:
好像两边的和都不好计算,于是来补全一下式子使得一方为定值,假设A选的集合为A,B选的集合为B,全集为T。
这样以后左边变成了一个定值,右边也变成了一个只和单次取的数相关的值,所以按照到所有的点的距离从大到小排序后依次取就可以得到答案了。
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;++i)
typedef long long ll;
using namespace std;
void File(){
freopen("by.in","r",stdin);
freopen("by.out","w",stdout);
}
const int maxn=2500+10;
int n;
long double ans;
struct node{
ll x,y;
long double val;
bool operator < (const node & tt) const {
return val>tt.val;
}
}a[maxn<<1];
long double get_dis(int f,int g){return sqrt((a[f].x-a[g].x)*(a[f].x-a[g].x)+(a[f].y-a[g].y)*(a[f].y-a[g].y));}
int main(){
File();
scanf("%d",&n); n<<=1;
REP(i,1,n)scanf("%lld%lld",&a[i].x,&a[i].y);
REP(i,1,n)REP(j,1,n)a[i].val+=get_dis(i,j);
sort(a+1,a+n+1);
REP(i,1,n)REP(j,i+1,n)ans+=get_dis(i,j);
REP(i,2,n)ans-=a[i++].val;
printf("%.3Lf\n",ans);
return 0;
}