Jzoj 2555. 【NOIP2011模拟9.7】雾雨魔理沙

题目介绍:

在幻想乡,雾雨魔理沙是住在魔法之森普通的黑魔法少女。话说最近魔理沙从香霖堂拿到了升级过后的的迷你八卦炉,她迫不及待地希望试试八卦炉的威力。在一个分上下两条长边之间就是这次八卦炉的攻击范围,在蓝色范围内的毛玉(红点)属于该此被击中的毛玉,如果一个毛玉刚好在边界上也视为被击中。毛玉击中以后就会消失,每次发射八卦炉得到分值是该次击中毛玉的分值和乘上这些毛玉平均的倍率,设该次击中的毛玉集合为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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值