10.18T7 简单坐标转换+DP

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

Hint

对于60%的数据:1 <= N <= 500 
对于100%的数据:1 <= N <= 2,000 
-10,000 <= x,y <= 10,000 
1 <= value,mul <= 100 

注意 π = 3.1415926
 
 
 
把坐标转换到y轴上面去然后排序,接着DP就可以了
code:
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #define N 100005 
 6 using namespace std;
 7 double pi=acos(-1.0);
 8 struct node{
 9     double x,y,mul,val;
10 }e[N];
11 bool cmp(const node&a,const node&b){
12     return a.y>b.y;
13 }
14 double sumval[N],summul[N],alpha,f[N];
15 int main(){
16     int n;
17     cin>>n;
18     for(int i=1;i<=n;i++){
19         cin>>e[i].x>>e[i].y>>e[i].val>>e[i].mul;
20     }
21     cin>>alpha;
22     double rate=tan(alpha*pi/180.0);
23     for(int i=1;i<=n;i++){
24         e[i].y=e[i].y-e[i].x*rate;
25     }
26     sort(e+1,e+n+1,cmp);
27     for(int i=1;i<=n;i++){
28         sumval[i]=sumval[i-1]+e[i].val;
29         summul[i]=summul[i-1]+e[i].mul;
30     }
31     f[0]=0;
32     for(int i=1;i<=n;i++){
33         for(int j=0;j<i;j++){
34             f[i]=max(f[i],f[j]+(sumval[i]-sumval[j])*(summul[i]-summul[j])/(i-j));
35         }
36     }
37     printf("%.3lf",f[n]);
38     return 0;
39 }

over

原文地址:https://www.cnblogs.com/saionjisekai/p/9813708.html