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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章