YL杯超级篮球赛
Time Limits: 1000 ms Memory Limits: 65536 KB
Description
一年一度的高一YL杯超级篮球赛开赛了。当然,所谓超级,意思是参赛人数可能多余5人。小三对这项篮球非常感兴趣,所以一场都没有落下。每个中午都准时守侯在篮球场看比赛。经过一个星期的研究,小三终于对篮球的技战术找到了一丝丝感觉了。他发现打YL杯的每个班都有一套相似的进攻战术:
1 :控球后卫带球到前场,找到一个最佳攻击点 ( x , y )
2 :所有除控卫以外的队员都从各自的当前位置迅速向 ( x , y ) 移动
3 :控球后卫根据场上情况组织进攻
这个战术对于一般情况是非常奏效的,但是每个队员毕竟不像小三一样每天精力过剩,每个队员都有一个疲劳指数W,显然对于每个队员的移动需要消耗一些能量。
假设一个队员从位置 ( x1 , 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
一个实数。表示所有队员集合到最佳攻击位置的能量消耗总和,答案保留两位小数。
Sample Input
1
1
0 0
Sample Output
0.00
题目大意
这道题上前面有一大串都是没用的。主干的意思大致是,题目给了你n个点,每个点都有一个常数 Wi ,和它的坐标( Ai , Bi )。
目前定义一个带有常数V点(X1,Y1)到一个坐标为(X2,Y2)的位置花费为
F(X1,Y1)=V(|X1−X2|+|Y1−Y2|)
那么,让你求一个位置(x,y),让所有点都走到这个位置,得到一个总的花费,求所有总的花费的最小值
解题思路
因为他求的点与点的距离并不是勾股定理,所以,这道题就变得简单了许多,点与点的距离,只跟横坐标与纵坐标的差距有关系,所以我们就可以将点的横坐标和纵坐标分开来讨论。
就拿横坐标来说,倘若所有的常数都为1,是不用想的太多的。
点数为奇数的情况,倘若每个点所在横坐标的位置如下:
a–>b–>c–>d–>e
你选取的位置的横坐标为x,将x从a移动到e会发现,
a–>b段上x与a拉开一个ab的距离,和bcde缩小了ab的距离,也就是缩小了3个ab,答案在减少
b–>c段上x与ab拉开一个bc的距离,和cde缩小了bc的距离,也就是缩小了1个bc,答案在减少
c–>d段上x与abc拉开一个cd的距离,和de缩小了cd的距离,也就是增加了1个cd,答案在增加
d–>e段上x与abcd拉开一个de的距离,和e缩小了de的距离,也就是增加了3个de,答案在增加
可以得出x在c的位置上是最优解
点数为偶数的情况,倘若每个点所在横坐标的位置如下:
a–>b–>c–>d–>e–>f
你选取的位置的横坐标为x,将x从a移动到e会发现,
a–>b段上x与a拉开一个ab的距离,和bcdef缩小了ab的距离,也就是缩小了4个ab,答案在减少
b–>c段上x与ab拉开一个bc的距离,和cdef缩小了bc的距离,也就是缩小了2个bc,答案在减少
c–>d段上x与abc拉开一个cd的距离,和def缩小了cd的距离,也就是不变
d–>e段上x与abcd拉开一个de的距离,和ef缩小了de的距离,也就是增加了3个de,答案在增加
e–>f段上x与abcde拉开一个ef的距离,和f缩小了ef的距离,也就是增加了3个ef,答案在增加
可以得出x在c-d的位置上是最优解
综上所述,我们可以发现,当所有常数都为一时,取中位数即可。但常数不为一怎么办?那就将常数为v的点看作v个这样的点,答案不影响。
求纵坐标的同理。
Codes:
#include<cstdio>
#include<cmath>
#include<cstring>
#define fo(i,x,y) for(int i=x;i<=y;i++)
using namespace std;
struct Point{
int x,y,t;
}a[50001];
int n,tot=0,ansx,ansy;
double ans=0.0;
int getx();
int gety();
void q(int,int);
void p(int,int);
int main()
{
scanf("%d",&n);
fo(i,1,n){scanf("%d",&a[i].t);tot+=a[i].t;}
fo(i,1,n)scanf("%d%d",&a[i].x,&a[i].y);
ansx=getx();ansy=gety();
fo(i,1,n)ans+=(abs(ansx-a[i].x)+abs(ansy-a[i].y))*a[i].t;
printf("%.2lf",ans);
}
int gety()
{
p(1,n);
int total=0;
fo(i,1,n)
{
total+=a[i].t;
if(total>=(tot+1)>>1)return(a[i].y);
}
}
int getx()
{
q(1,n);
int total=0;
fo(i,1,n)
{
total+=a[i].t;
if(total>=(tot+1)>>1)return(a[i].x);
}
}
void q(int h,int t)
{
int l=h,r=t,m=a[(h+t)>>1].x;
do
{
while(a[l].x<m)l++;
while(a[r].x>m)r--;
if(l<=r)
{
a[0]=a[l];a[l]=a[r];a[r]=a[0];
l++;r--;
}
}while(!(l>r));
if(h<r)q(h,r);if(l<t)q(l,t);
}
void p(int h,int t)
{
int l=h,r=t,m=a[(h+t)>>1].y;
do
{
while(a[l].y<m)l++;
while(a[r].y>m)r--;
if(l<=r)
{
a[0]=a[l];a[l]=a[r];a[r]=a[0];
l++;r--;
}
}while(!(l>r));
if(h<r)p(h,r);if(l<t)p(l,t);
}