Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
雁过留声——贪心+优先队列这题的思路方向是:做最好的自己 想象一下,现在到了第i轮,面对着冲天的黑雾,弥漫的烟气,以及巨大的黑龙。这时, 突然反思:怎么判断我我是否已经尽心尽力了呢? 首先, 如果现在还剩下a点HP,a>A[i],却不主动选择攻击,那就是十分可耻的行为。为什么? 其实,如果以后某次大难临头,不得不需要着A[i]点HP,那么那时可以让时光倒流,回 到现在,撤销攻击,然后再该干嘛干嘛。 接下来, 如果不得不让时光倒流,那么我肯定是要选择撤销能够得到HP最多的那次攻击。每次攻 机都是等效的,既然已经不得不撤销一次,干嘛不让这个撤销达到最大收益呢? 这样,得到算法: 扫描A[i],攻击,同时将Max(y,A[i])送入优先队列。 如果当前HP<0,那么时光倒流,弹出队列中的最大值,累加到HP中,直到当前HP>0,即 我复活了为止。 关键代码: struct Heap{ int d[NMax],hc; Heap(){hc=0;} void in(int a){ int x,t; d[hc++]=a; for (x=hc-1;x && d[x]>d[(x-1)>>1];x=((x-1)>>1)){ t=d[x];d[x]=d[(x-1)>>1];d[(x-1)>>1]=t; } } int max(){return d[0];} int outMax(){ int ret,t,x,y; ret=d[0]; if (!hc)return 0; d[0]=d[hc-1];hc--; x=0; while ((x<<1)+1<hc){ y=x; if (d[(x<<1)+1]>d[y])y=(x<<1)+1; if ((x<<1)+2<hc && d[(x<<1)+2]>d[y])y=(x<<1)+2; if (x==y)break; t=d[x];d[x]=d[y];d[y]=t; x=y; } return ret; } }heap; for (int ii=0;ii<N;ii++){ scanf("%d",&w); if (bs<s+x)bs=s+x; if (H2<=x){ // i can kill him H2-=x; printf("Win\n%d\n",ii+1); break; }else if (H1>w){ // i try to attack H1-=w;H2-=x; heap.in(w+Max(y-w,0)); s+=x; }else{ //i have to defend H1-=w;H2-=x; heap.in(w+Max(y-w,0)); s+=x; while (heap.hc && H1<=0){ H1+=heap.outMax();s-=x;H2+=x; } } } if (H2>0)printf("Lose\n%d\n",bs); Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator