scauoj_11158 切水果

来源:互联网 发布:淘宝联盟佣金只有一半 编辑:程序博客网 时间:2024/04/30 13:45

11158 切水果

时间限制:1000MS  内存限制:65535K
提交次数:638 通过次数:82

题型: 编程题   语言: G++;GCC

Description

   Lrc是校队里面的总所周知的全才王,他不仅是一个excelent acmer,也不仅是一个chess master,更是一个crazy game player。切水果,正是他最喜欢玩的手机游戏之一。为了避免有人没玩过,下面介绍一下Lrc是怎么玩这个游戏的~-~1) 整个屏幕是一个笛卡尔坐标系。2) 在某个时刻,屏幕上会出现灰常多的水果,西瓜、草莓神马的,当然还有一种,炸弹。3) 每个时刻用手指在屏幕上划过,切中水果可以得到一定得分数,切到炸弹就要扣分。4) 每个时刻最多只能切一刀,至于一刀切多少个可以自由控制。5) 第t时刻没有被切的水果,将不会出现在下一个时刻。6) 由于Lrc 骨骼奇精,所以手指在屏幕上只能划线段,也就是说只有在同一线段上的水果他才能在同一时间内切到。(友情提醒,线段不仅是斜的,也可以是水平和垂直的哦)。   由于Lrc比较神,每次他总能得到最高分。嘿嘿,你想要成为未来的Acmer吗?那就必须帮Lrc算出他的分数咯O(∩_∩)O~----------------------------------------------------------------------------------------------------------------------------------------   PS:记住,Acmer要有永不言弃的精神,花一天过了这个题,值得了~~~~~       还有,输出的句子,请直接复制题目上面的,不要手打,以防出错!!!(出题人Ly)



输入格式

第一行3个整数n(n<=150),m(m<=20),k(0=<k<=1e9+7),分别代表这一局出现的水果(炸弹)数,水果种类,以及每切中一个炸弹要扣的分数。紧接着一行m个整数v1,v2,v3….vm(0<=vi<=10000),分别代表m种水果的分数。接下来n行分别代表一个水果(炸弹),每行4个整数x,y,p,t(x,y代表该水果的坐标,p代表该水果得种类(p=0时为炸弹),t代表该水果出现的时刻)(-1000<=x,y<=1000,0<=p<=m,0<=t<=90)。


输出格式

若Lrc 得到的分数不大于零,请输出“Poor Lrc!!!”,因为他将要受到强神的BS;否则,输出“God Lrc, you’ve got S points!”,S是Lrc得到的分数。


输入样例

sample#1:1 1 10100 0 1 1sample#2:6 3 201 2 100 1 2 1100 100 2 20 2 0 10 3 3 11 1 3 20 0 1 1


输出样例

sample#1:God Lrc, you’ve got 10 points!sample#2:God Lrc, you’ve got 22 points!


提示

样例中的sample#1,sample#2不属于输入输出的一部分,只是说明其不是一个输入和输出。
Attention: 炸弹当一个水果就行了!!切到炸弹不结束!!

来源

Ly

作者

scau_acm


题解:直接模拟啦。。把相同时间的归在一起,再把同一线段的放在一起,求最大子段和(dp)就可以了

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <map>#include <stack>using namespace std;typedef struct boom{    int x,y,p,t;}boom;boom w[200],q[200];int fruit[200],ans;map<double,int> flag1,flag2;stack<int> r;bool cmp(boom a,boom b){    if(a.t<b.t)        return true;    else if(a.t==b.t)    {        if(a.x<b.x)            return true;        else if(a.x==b.x)        {            if(a.y<b.y)                return true;            else                return false;        }        else            return false;    }    else        return false;}void solve(int n){    int k=w[1].t,len=0;    w[n+1].t=-100;    for(int i=1;i<=n;i++)    {        if(w[i].t==k)        {            q[++len]=w[i];//出现时间相同        }        if(w[i+1].t!=k)//不相同        {            int maxend=0;            //printf("当前的时刻为%d\n\n",k);            for(int j=1;j<=len;j++)            {                for(int l=j;l<=len;l++)                {                    double u=(q[j].y-q[l].y);                    if(q[j].x-q[l].x!=0)//斜率存在                    {                        u=1.0*u/(q[j].x-q[l].x);//斜率                        if(flag1.find(u)==flag1.end())//该斜率的没算过                        {                            r.push(q[j].p);                            if(j!=l)                            r.push(q[l].p);//j,l水果进栈                            flag1[u]=1;                            int s=0;                            for(int m=l+1;m<=len;m++)//讲这一时刻所有斜率为u的进栈                            {                                if(q[m].x!=q[j].x)                                {                                    double u0=1.0*(q[m].y-q[j].y)/(q[m].x-q[j].x);                                    if(fabs(u0-u)<1e-9)                                    {                                            r.push(q[m].p);                                    }                                }                            }                            //求最大子段和                            while(!r.empty())                            {                                int v=r.top();                                r.pop();                                if(s>0)                                    s+=fruit[v];                                else                                    s=fruit[v];                                maxend=max(maxend,s);                            }                        }                    }                    else//斜率不存在                    {                        double u=1.0*q[j].x;                        if(flag2.find(u)==flag2.end())                        {                            flag2[u]=1;                            r.push(q[j].p);                            if(j!=l)                            r.push(q[l].p);                        int s=0;                        for(int m=l+1;m<=len;m++)                        {                            if(q[m].x==q[j].x)                            {                                r.push(q[m].p);                            }                        }                        //求最大字段和                        while(!r.empty())                        {                            int v=r.top();                            r.pop();                            if(s>0)                                s+=fruit[v];                            else                                s=fruit[v];                            maxend=max(maxend,s);                        }                        }                    }                }            }            ans+=maxend;            flag1.clear();            flag2.clear();            len=0;            k=w[i+1].t;            //printf("获得了%d分数\n",maxend);        }    }}int main(){    int n,m,k;    cin>>n>>m>>k;    fruit[0]=-k;    for(int i=1;i<=m;i++)        cin>>fruit[i];    for(int i=1;i<=n;i++)        cin>>w[i].x>>w[i].y>>w[i].p>>w[i].t;    sort(w+1,w+1+n,cmp);    solve(n);    if(ans>0)        printf("God Lrc, you’ve got %d points!\n",ans);    else        printf("Poor Lrc!!!\n");    return 0;}


0 0