题目介绍:
在幻想乡,雾雨魔理沙是住在魔法之森普通的黑魔法少女。话说最近魔理沙从香霖堂拿到了升级过后的的迷你八卦炉,她迫不及待地希望试试八卦炉的威力。在一个分上下两条长边之间就是这次八卦炉的攻击范围,在蓝色范围内的毛玉(红点)属于该此被击中的毛玉,如果一个毛玉刚好在边界上也视为被击中。毛玉击中以后就会消失,每次发射八卦炉得到分值是该次击中毛玉的分值和乘上这些毛玉平均的倍率,设该次击中的毛玉集合为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个实数,表示最大分值,保留三位小数
TJ
这题其实是一个高等数学题,运用到了神奇的三角函数,因为输入给了你角alpha的度数,附个图
刚看这题,我们几乎是毫无头绪,因为这是一个二维的覆盖问题,于是根据“二维”,我们可以很容易的想到把它转换成“一维”,所以接下来的任务就是把所有点压到X轴上。于是乎,一个新的问题又出现了:如何把它们压到X轴上呢?我们都知道一次函数y=kx+b
如下图:
接着,我们不难发现x,y都是我们知道的,而经过一系列的移项,我们发现我们要求的值只和k,b有关系,这时,学过三角函数的同学就会发现,k可以用正切函数(tan)来算出(k=tan(α*π/360));而知道了k,x,y之后,b也就不难求了(b=y-kx),求出后将所有点按b排序,再弄一个DP,设f[i]表示取到第i个所能获得的最大价值,方程自行脑补
贴段代码
uses math;
var
i,j,m,n,x,y,alpha:longint;
k:real;
v,u,sv,su:array[0..2001] of longint;
b,f:array[0..2001] of real;
zb:array[1..2001,1..2] of longint;
procedure qs(l,r:longint);
var
i,j,t1:longint;
mid:real;
t:real;
begin
i:=l;
j:=r;
mid:=b[(i+j) div 2];
repeat
while b[i]<mid do inc(i);
while b[j]>mid do dec(j);
if i<=j then
begin
t:=b[i];b[i]:=b[j];b[j]:=t;
t1:=v[i];v[i]:=v[j];v[j]:=t1;
t1:=u[i];u[i]:=u[j];u[j]:=t1;
inc(i);
dec(j);
end;
until i>j;
if i<r then qs(i,r);
if j>l then qs(l,j);
end;
begin
readln(n);
for i:=1 to n do
begin
readln(zb[i,1],zb[i,2],v[i],u[i]);
end;
readln(alpha);
k:=tan(alpha*3.1415926/180);
for i:=1 to n do
begin
x:=zb[i,1];
y:=zb[i,2];
b[i]:=y-k*x;
end;
qs(1,n);
for i:=1 to n do
begin
sv[i]:=v[i]+sv[i-1];
su[i]:=u[i]+su[i-1];
end;
for i:=1 to n do
writeln(sv[i],' ',su[i]);
for i:=1 to n do
begin
for j:=1 to i do
f[i]:=max(f[i],f[j-1]+(sv[i]-sv[j-1])*(su[i]-su[j-1])/(i-j+1));
end;
writeln(f[n]:0:3);
close(input);close(output);
end.