【CJOJ P2110】YL杯超级篮球赛

【CJOJ P2110】YL杯超级篮球赛

Description

一年一度的高一YL杯超级篮球赛开赛了。当然,所谓超级的意思是参赛人数可能多于5人。小三对这场篮球赛非常感兴趣,所以一场都没有落下。每天中午都准时守候在篮球场看比赛。经过一个星期的研究,小三终于对篮球的技战术找到了一丝丝感觉。他发现打YL杯的每个班都有一套相似的进攻战术:
1.控球后卫带球到前场,找到一个最佳攻击点(x,y)。
2.所有除控卫以外的队员都从各自的当前位置迅速向(x,y)移动。
3.控球后卫根据场上情况组织进攻。
这个战术对于一般情况是非常奏效的,但是每个队员毕竟不像小三一样每天精力过剩,每个队员都有一个疲劳指数w,显然对于每个队员的移动需要消耗一些能量。
假设一个队员从位置xl,y1)移动到(x,y)的能量消耗为w*(ABS(x-x1)+ABS(y-y1)),这里ABS为绝对值函数,那么我们希望整个队伍一次进攻的能量消耗当然是越少越好。显然能量消耗的多少直接取决于控球后卫对于攻击点(x,y)的选择。
因为参赛人数众多,所以小三希望你能编写一个程序,帮他找出某个时刻的最佳攻击点。

Input

第一行:一个整数N,表示篮球队人数
第二行:一共N个整数,其中的第i个数Wi表示第i个队员的疲劳指数。
第3~N+2行:每一行两个整数x和Y,表示其中的第i+2行,表示第i个队员的当前位置的横坐标和纵坐标。

Output

一个实数。表示所有队员集合到最佳攻击位置的能量消耗总和,答案保留两位小数。

样例输入

1
1
0 0

样例输出

0.00

数据规模

n<=50000
0<w<=1000
0<x,y<=1000000

题解

这道题有点像士兵站队问题,每一个人的疲劳值直接看成重复的几个人即可。可以自己试着画一下,发现会很简单。把每个人的横坐标、纵坐标全部排序,然后依次就中位数计算就可以了,具体的证明请自己温习初一的绝对值距离。这道题的写法很好的利用到了中位数/绝对值的使用。

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath> 
#include<algorithm>
using namespace std;
int w[50001],n;
long long sum=0;
struct dsl
{
	    int a;
	    int w;
};//结构体定义
 
bool cmp(dsl k,dsl d)
{
	    return k.a<d.a;
}//比较函数(方便直接调用sort)
dsl x[50001],y[50001];
 
int main()
{
	               //读入 
		    long long cd=0;
    	    cin>>n;
    	    for(int i=1;i<=n;++i)
    	    {
    	          scanf("%d",&w[i]);
    	          x[i].w=w[i];
		          y[i].w=w[i];
    	          cd+=w[i];
            }            
    	    for(int i=1;i<=n;++i)
    	          scanf("%d%d",&x[i].a,&y[i].a);
                    
                       //排序 
             sort(&x[1],&x[n+1],cmp);
             sort(&y[1],&y[n+1],cmp); 
        		       //计算 
            int k;
            cd=int(((cd+1)/2)+0.5);
            long long g=cd;
            for(int i=1;i<=n;++i)
             {
         	        cd-=x[i].w;
         	        if(cd<=0){k=i;break;}
		     }
            for(int i=1;i<=n;++i)
                 sum+=abs(x[k].a-x[i].a)*x[i].w;
         
         
            cd=g;
            for(int i=1;i<=n;++i)
             {
         	        cd-=y[i].w;
         	        if(cd<=0){k=i;break;}
		     }
	        for(int i=1;i<=n;++i)
	             sum+=abs(y[k].a-y[i].a)*y[i].w;
	                    //利用绝对值进行计算
	     
	     		       //输出	
	        cout<<sum<<".00"<<endl;
	                   //由绝对值的最小值和题目数据可知,结果一定是一个整数
	                   //但是要求输出的事小数点后两位,所以直接打印".00"
    	    return 0;
}
posted @ 2017-07-17 17:31  小蒟蒻yyb  阅读(420)  评论(0编辑  收藏  举报