2018暑期练习题1 B 雾雨魔理沙

2018暑期练习题1 B 雾雨魔理沙

问题描述

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

蓝色部分上下两条长边之间就是这次八卦炉的攻击范围,在蓝色范围内的毛玉(红点)属于该此被击中的毛玉,如果一个毛玉刚好在边界上也视为被击中。毛玉击中以后就会消失,每次发射八卦炉得到分值是该次击中毛玉的分值和乘上这些毛玉平均的倍率,设该次击中的毛玉集合为S,则分值计算公式为:

Score=SUMvalue[i]|iSSUMmul[i]|iS/|S|

其中|S|表示S的元素个数。魔理沙将会使用若干次八卦炉,直到把所有毛玉全部击中。任意两次攻击的范围均不重叠。最后得到的分值为每次攻击分值之和。现在请你计算出能够得到的最大分值。

输入格式

第1行:1个整数N,表示毛玉个数

第2..N+1行:每行四个整数x, y, value, mul,表示星星的座标(x,y),以及value和mul

第N+2行:1个整数α,表示倾斜角角度,0°到180°

输出格式

第1行:1个实数,表示最大分值,保留三位小数

解法

不知道该怎么讲…直接放伪代码吧

1.把点按从上到下(或者从下到上)的顺序排序(斜率已知,点的座标已知,可以求出截距)

2.动态规划:f[i]=f[j]+sumj+1,i,0<=j<i ,其中sum{j+1,i}表示j+1i 号点的分值(总分*平均倍率)

代码

我这代码还把同一条直线上的点合并了,因为它们肯定会被一根直线消掉

然而并没有这个必要,徒增代码复杂度,害我调了好久= =

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define pi 3.1415926
#define N 2100
using namespace std;
struct node{int x,y,v,mul,id;}p[N];
struct Node{int v,mul,Size;double b;}New[N];
double Max(double a,double b){return a>b?a:b;}
bool cmp(node a,node b){return a.id<b.id;}
bool cmpp(Node aa,Node bb){return aa.b<bb.b;}
double f[N];
int main(){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d%d",&p[i].x,&p[i].y,&p[i].v,&p[i].mul);
        p[i].id=i;
    }
    double al;scanf("%lf",&al);
    al=tan(pi*al/180);
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++){
            if(p[j].id!=j)continue;
            double k=(double)(p[j].y-p[i].y)/(p[j].x-p[i].x);
            if(k==al)p[j].id=i;
        }
    sort(p+1,p+n+1,cmp);int cnt=0;
    for(int i=1;i<=n;i++){
        if(p[i].id!=p[i-1].id)cnt++;
        New[cnt].v+=p[i].v,New[cnt].mul+=p[i].mul,New[cnt].Size++;
        New[cnt].b=1.0*p[i].y-al*p[i].x;
    }
    sort(New+1,New+cnt+1,cmpp);
    for(int i=1;i<=cnt;i++)
        New[i].v+=New[i-1].v,New[i].mul+=New[i-1].mul,New[i].Size+=New[i-1].Size;
    for(int i=1;i<=cnt;i++)
        for(int j=0;j<i;j++)
            f[i]=Max(f[i],f[j]+1.0*(New[i].v-New[j].v)*(New[i].mul-New[j].mul)/(New[i].Size-New[j].Size));
    printf("%.3lf",f[cnt]);return 0;
}
发布了129 篇原创文章 · 获赞 16 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章