Description
在幻想乡,雾雨魔理沙是住在魔法之森普通的黑魔法少女。话说最近魔理沙从香霖堂拿到了升级过后的的迷你八卦炉,她迫不及待地希望试试八卦炉的威力。在一个二维平面上有许多毛玉(一种飞行生物,可以视为点),每个毛玉具有两个属性,分值value和倍率mul。八卦炉发射出的魔法炮是一条无限长的直线形区域,可以视为两条倾斜角为α的平行线之间的区域,平行线之间的距离可以为任意值,如下图所示:
蓝色部分上下两条长边之间就是这次八卦炉的攻击范围,在蓝色范围内的毛玉(红点)属于该此被击中的毛玉,如果一个毛玉刚好在边界上也视为被击中。毛玉击中以后就会消失,每次发射八卦炉得到分值是该次击中毛玉的分值和乘上这些毛玉平均的倍率,设该次击中的毛玉集合为S,则分值计算公式为:
Score = SUM{value[i] | i 属于 S} * SUM{mul[i] | i 属于 S} / |S|
其中|S|表示S的元素个数。魔理沙将会使用若干次八卦炉,直到把所有毛玉全部击中。任意两次攻击的范围均不重叠。最后得到的分值为每次攻击分值之和。现在请你计算出能够得到的最大分值。
Input
第1行:1个整数N,表示毛玉个数
第2..N+1行:每行四个整数x, y, value, mul,表示星星的坐标(x,y),以及value和mul
第N+2行:1个整数α,表示倾斜角角度,0°到180°
Output
第1行:1个实数,表示最大分值,保留三位小数
Sample Input
3
1 3 3 1
2 1 2 2
3 4 2 1
45
Sample Output
9.333
【数据范围】
对于60%的数据:1 <= N <= 500
对于100%的数据:1 <= N <= 2,000
-10,000 <= x,y <= 10,000
1 <= value,mul <= 100
【注意】
π = 3.1415926
题解
这一题涉及初三高一的知识,本人尚未涉及,但有高人给出公式
先排序,用公式得出一次函数的斜率 p:=sin(p*pi/180)/cos(p*pi/180)
得出来只有就是一个背包呢。
代码
type
nod=record
x,y,v,m:longint;
end;
var
a:array[0..2000]of nod;
f,b:array[0..2000]of double;
sm,sv:array[0..2000]of longint;
p:double;
i,j,n:longint;
function max(a,b:double):double;
begin
if a<b then exit(b)
else exit(a);
end;
procedure sort(l,r:longint);
var
t:nod;
i,j,m:longint;
begin
i:=l;j:=r;m:=a[(l+r)shr 1].x;
repeat
while a[i].x<m do inc(i);
while a[j].x>m do dec(j);
if not(i>j) then
begin
t:=a[i];a[i]:=a[j];a[j]:=t;
inc(i);dec(j);
end;
until i>j;
if i<r then sort(i,r);
if l<j then sort(l,j);
end;
procedure sort2(l,r:longint);
var
t,m:double;
i,j:longint;
tt:nod;
begin
i:=l;j:=r;m:=b[(l+r)shr 1];
repeat
while b[i]<m do inc(i);
while b[j]>m do dec(j);
if not(i>j) then
begin
t:=b[i];b[i]:=b[j];b[j]:=t;
tt:=a[i];a[i]:=a[j];a[j]:=tt;
inc(i);dec(j);
end;
until i>j;
if l<j then sort2(l,j);
if i<r then sort2(i,r);
end;
function calc(l,r:longint):double;
var
v,m:int64;
begin
v:=sv[r]-sv[l-1];
m:=sm[r]-sm[l-1];
exit(v*m/(r-l+1));
end;
procedure main;
begin
readln(n);
for i:=1 to n do
with a[i] do
readln(x,y,v,m);
readln(p);
if p=90 then sort(1,n)
else
begin
p:=sin(p*pi/180)/cos(p*pi/180);
for i:=1 to n do b[i]:=-p*a[i].x+a[i].y;
sort2(1,n);
end;
for i:=1 to n do
begin
sv[i]:=sv[i-1]+a[i].v;
sm[i]:=sm[i-1]+a[i].m;
end;
fillchar(f,sizeof(f),172);
f[0]:=0;
for i:=1 to n do
for j:=0 to i-1 do
if (a[i].x=a[j].x)and(a[i].y=a[j].y) then break
else
f[i]:=max(f[i],f[j]+calc(j+1,i));
writeln(f[i]:0:3);
end;
begin
main;
end.