| ||||||||||
| 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