P2455雾雨魔理沙

在幻想乡,雾雨魔理沙是住在魔法之森普通的黑魔法少女。话说最近魔理沙从香霖堂拿到了升级过后的的迷你八卦炉,她迫不及待地希望试试八卦炉的威力。在一个二维平面上有许多毛玉(一种飞行生物,可以视为点),每个毛玉具有两个属性,分值value和倍率mul。八卦炉发射出的魔法炮是一条无限长的直线形区域,可以视为两条倾斜角为α的平行线之间的区域,平行线之间的距离可以为任意值,如下图所示:

蓝色部分上下两条长边之间就是这次八卦炉的攻击范围,在蓝色范围内的毛玉(红点)属于该此被击中的毛玉,如果一个毛玉刚好在边界上也视为被击中。毛玉击中以后就会消失,每次发射八卦炉得到分值是该次击中毛玉的分值和乘上这些毛玉平均的倍率,设该次击中的毛玉集合为S,则分值计算公式为:
Score = SUM{value[i] | i 属于 S} * SUM{mul[i] | i 属于 S} / |S|
其中|S|表示S的元素个数。魔理沙将会使用若干次八卦炉,直到把所有毛玉全部击中。任意两次攻击的范围均不重叠。最后得到的分值为每次攻击分值之和。现在请你计算出能够得到的最大分值。

题解

通过固定角度的直线的高度来确定顺序
然后dp一下即可
dp[i]表示前i个最大值,所以dp[i]=dp[j-1]+(sum[i]-sum[j-1)*(v[i]-v[j-1])/(i-j+1)

代码

#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <cmath>
#include <algorithm>
using namespace std;
const double pi=3.1415926;
struct node{
    int x,y,v,m;
    double b;   
};
int n;
double sa[2005];
double sm[2005];
node pos[2005];
double arc;
double k;
bool cmp1(node a,node b){
    return a.b<=b.b;
}
double f[2008];
int main()
{
    int i,j;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        int x,y,v,m;
        scanf("%d%d%d%d",&x,&y,&v,&m);
        pos[i].x=x;pos[i].y=y;pos[i].v=v;pos[i].m=m;
    }
    cin>>arc;
    double num=arc/180;
    k=tan(num*pi);
    for(i=1;i<=n;i++)
    {
        pos[i].b=pos[i].y-k*pos[i].x;
    }
    sort(pos+1,pos+n+1,cmp1);

    for(i=1;i<=n;i++){
        sa[i]=sa[i-1]+pos[i].v;
        sm[i]=sm[i-1]+pos[i].m;
    }

    for(i=1;i<=n;i++)
    {
        for(j=1;j<=i;j++)
        {
            f[i]=max(f[i],f[j-1]+(sa[i]-sa[j-1])*(sm[i]-sm[j-1])/(i-j+1));
        }
    }
    printf("%.3f",f[n]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值