[bzoj3709][PA2014]Bohater_贪心

bzoj-3709 PA-2014 Bohater

题目大意:在一款电脑游戏中,你需要打败n只怪物(从1到n编号)。为了打败第i只怪物,你需要消耗d[i]点生命值,但怪物死后会掉落血药,使你恢复a[i]点生命值。任何时候你的生命值都不能降到0(或0以下)。请问是否存在一种打怪顺序,使得你可以打完这n只怪物而不死掉。

数据范围:$1\le n,Hp_{ori}\le 10^5$,$0\le d_i,a_i\le 10^5$。



想法

期望找到这样一个顺序是的打完不死掉。

我们把怪物分成两种。

第一种是打完了之后加血的,第二种是打完了之后扣血的。

第一种的话,我们按照攻击力从低到高排序这个很好理解。

第二种我们按照回写的高低排序这样的话反正左右都是打,显然最后回血越多的越优先。

最后,毋庸置疑的是先打第一种后打第二种。

代码

#include <bits/stdc++.h>
#define N 100010
using namespace std;
typedef long long ll;
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0,f=1; char c=nc(); while(c<48) {if(c==‘-‘) f=-1; c=nc();} while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x*f;}
struct Node {ll atk,hp; int id;}a[N];
inline bool cmp(const Node &a,const Node &b)
{
	int x=a.hp-a.atk,y=b.hp-b.atk;
	if(x>=0 && y>=0) return a.atk < b.atk;
	else if(x*y <= 0) return x >= 0;
	else return a.hp>b.hp;
}
int main()
{
	ll n=rd(),m=rd();
	for(int i=1;i<=n;i++) a[i].atk=rd(),a[i].hp=rd(),a[i].id=i;
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++)
	{
		m-=a[i].atk;
		if(m<=0) puts("NIE"),exit(0);
		m += a[i].hp;
	}
	puts("TAK");
	for(int i=1;i<=n;i++) printf("%d ",a[i].id);
	puts("");
	return 0;
}

小结:这种贪心题一定要多积累。

原文地址:https://www.cnblogs.com/ShuraK/p/11053823.html

时间: 2024-08-29 05:03:56

[bzoj3709][PA2014]Bohater_贪心的相关文章

bzoj3709: [PA2014]Bohater 贪心

~~~题面~~~ 题解: 首先有一个比较明显的策略,肯定先要把能带给自己受益的先选完,然后再以最佳状态去打那些会给自己带来损失的怪. 对于前一部分(可以带来受益的怪),显然我们需要先从代价小的打起,因为这样可以把生命值越积越多,打代价大的怪也更容易成功. 那么对于后一部分怎么办呢?我们需要从受益大的打起,为什么? 证明: 假设一个怪的受益为back,代价为cost,那么首先假设我们打完所有怪之后剩下have的生命值,那么have的大小是固定的,不会随着操作顺序而改变,因此我们可以考虑用这个来倒推

【贪心】bzoj3709 [PA2014]Bohater

把怪分成两类看: 一.回血>损血 则若先杀损血少的再杀损血多的,则为当前这一步提供了更高的可能性.因为血量是单增的,所以尽量用较少的血量去干♂耗血较少的怪物. 二.回血<损血 则若先杀回血多的再杀回血少的,则为下一步提供了更高的可能性.当前这一步的可能性也没有减少,因为即使回血多的损血很多,但是由于此时血量已经是单减的了,所以若此时无法杀掉损血多的,将来也不能. ORZ TimeMachine And ZKY 1 #include<cstdio> 2 #include<ios

3709: [PA2014]Bohater 贪心

傻傻的. 看到题目猜是贪心.结果只搞出了加血 > 减血的情况(很显然这种情况下把减血量从下到大排就可以了). 下面讲一下 减血 > 加血的,顺便给出我的证明. 对于这种情况,网上许多题解都是说把加血从大到下排就可以了.然而蒟蒻我还是不大明白,所以简单证了一下.如果错了,请指正. 设当前血量为 z, 存在i, j 使得 a[i] > a[j] 若先杀掉 j, 比先杀掉 i 优,(或者说存在先杀掉 j,后杀掉 i 能解决的情况而 先杀掉 i, 后杀掉 j 无法满足.) 那么 z - (d[i

bzoj3709 [PA2014]Bohater

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3709 [题解] 打完怪最后的体力是固定的,设为lst 我们考虑回血量>=扣血量的怪,这些肯定优先打,顺序肯定是按照扣血量从小到大打,这一定是最优策略,打不了就是NIE了 接着由于lst固定,我们考虑扣血量>回血量的怪,就相当于从lst开始 每次打一个怪吐出"回血量"这么多的血,增加"扣血量"这么多的血. 于是从后往前,就是按回血量从小到大打,依次判

bzoj 3709: [PA2014]Bohater 贪心

code: #include <bits/stdc++.h> #define N 100005 #define LL long long using namespace std; void setIO(string s) { string in=s+".in"; freopen(in.c_str(),"r",stdin); } struct data { LL a,d; int id; data(LL a=0,LL d=0,int id=0):a(a),

待 题表

题表 达哥终极杂题表Bzoj2839 hdu6021 Codeforces 804DBzoj2248 hdu5575 Codeforces 786CBzoj2013 bzoj2676 Codeforces 803CBzoj2386 bzoj3782 Codeforces 813DBzoj2699 cogs1667 Codeforces 814DBzoj4798 bzoj2064 Codeforces 814EBzoj4639 bzoj3505 Codeforces 815ABzoj4417 bz

我与PA有个约定

bzoj3546:[ONTAK2010]Life of the Partybzoj3548:[ONTAK2010]Partybzoj3709:[PA2014]Bohaterbzoj3710:[PA2014]Ciagibzoj3711:[PA2014]Druzyny ****bzoj3713:[PA2014]Iloczynbzoj3714:[PA2014]Kuglarzbzoj3715:[PA2014]Lustrabzoj3716:[PA2014]Muzeumbzoj3717:[PA2014]Pa

省选之前的未完成的计划(截至到省选)

PLAN OF THE COMING HEOI good problems:-bzoj4823:[Cqoi2017]老C的方块 [*]-bzoj3171:[Tjoi2013]循环格 [*]-bzoj4200:[Noi2015]小园丁与老司机 [*]-bzoj1061:[Noi2008]志愿者招募 [*]-bzoj3600:没有人的算术 [*]-bzoj2806:[Ctsc2012]Cheat [*]-bzoj2219:数论之神 [*]-bzoj2595:[Wc2008]游览计划 [*]-bzoj

【BZOJ3721】PA2014 Final Bazarek 贪心

[BZOJ3721]PA2014 Final Bazarek Description 有n件商品,选出其中的k个,要求它们的总价为奇数,求最大可能的总价. Input 第一行一个整数n(1<=n<=1000000),表示商品数量.接下来一行有n个整数,表示每件商品的价格,范围在[1,10^9].接下来一行有一个整数m(1<=m<=1000000),表示询问数量.接下来m行,每行一个整数k[i](1<=k[i]<=n). Output 对于每个询问,输出一行表示保证奇数的