[ural1397]Points Game——博弈+贪心

题目大意:

给出平面2n点,有两个玩家游戏。每个回合,玩家A可以取走一个点,然后玩家B取走一个。经过n个回合没有点了,结束比赛。一个玩家的得分是他所取走的所有两两之间的欧几里得距离的和,得分最高者获胜。A和B都是聪明人,求两者分数之差为多少。

思路:

好像两边的和都不好计算,于是来补全一下式子使得一方为定值,假设A选的集合为A,B选的集合为B,全集为T。

ans=i,jA,i<jdis(i,j)i,jB,i<jdis(i,j) a n s = ∑ i , j ∈ A , i < j d i s ( i , j ) − ∑ i , j ∈ B , i < j d i s ( i , j )

ans=(i,jA,i<jdis(i,j)+iA,jBdis(i,j)+i,jB,i<jdis(i,j))(iA,jBdis(i,j)+i,jB,i<jdis(i,j)+i,jB,i<jdis(i,j)) a n s = ( ∑ i , j ∈ A , i < j d i s ( i , j ) + ∑ i ∈ A , j ∈ B d i s ( i , j ) + ∑ i , j ∈ B , i < j d i s ( i , j ) ) − ( ∑ i ∈ A , j ∈ B d i s ( i , j ) + ∑ i , j ∈ B , i < j d i s ( i , j ) + ∑ i , j ∈ B , i < j d i s ( i , j ) )

ans=i,jT,i<jdis(i,j)iBjTdis(i,j) a n s = ∑ i , j ∈ T , i < j d i s ( i , j ) − ∑ i ∈ B ∑ j ∈ T d i s ( i , j )

这样以后左边变成了一个定值,右边也变成了一个只和单次取的数相关的值,所以按照到所有的点的距离从大到小排序后依次取就可以得到答案了。

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值