Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

雁过留声——贪心+优先队列

Posted by fanhqme at 2009-11-22 21:38:15 on Problem 3465 and last updated at 2009-11-23 10:58:11
这题的思路方向是:做最好的自己

想象一下,现在到了第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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator