P4025 [PA2014]Bohater

一句话题意:

Link

给你 \(n\) 只怪物,打每个怪物需要扣除一定的血量,打完之后会回复一些血量。

你现在有初始血量 \(z\) 点,让你设计一种打怪方案是所有的怪的可以被打完。

solution:

一个很神奇的贪心。

首先我们把每个怪物分为两类,一类是回血怪,打完之后能回血的那种,另一类就是掉血怪。

我们把这两种怪物分开来考虑。

一个显然的策略就是先打回血怪再打掉血怪,不然先打掉血怪的话,血都掉没了你还怎么打其他的怪。

也就是说我们要先猥琐发育一波,等血量升高了(升满级了)再打掉血怪。

考虑同种怪物之间怎么安排顺序:

1.对于回血怪:

我们要尽可能先打血量少的。假如说你先打回血量多的,遇到下面一组样例你就 GG 了。

当前血量 \(10\) ,打 boss 掉血量 \(100\) ,回血量 \(10000\) 的。

这种情况你发现他虽然回血量比较多,但是你打不动他。

所以还是要先猥琐发育一波,等血量上来了,在打这个怪。

2.对于掉血怪:

一开始我是按血量从高到低排序的,可连交了几发都 \(WA\) 了,才发现这样写是不对的。

这是因为你可能会遇到一种情况就是 一个怪物他血量比较高,但回血量少。

这时候我们在打完所有的回血怪之后,第一个打他就会让我们的血量立刻降下来,导致后面的怪物都打不了。

所以我们要先紧着回血多的怪物打,是我们的血量尽可能的保持一个很高的状态。

然后这道题就做完了。

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define int long long
int n,z,x,y,cnt1,cnt2;
struct node
{
	int id,x,y;
}a[100010],b[100010];
inline int read()
{
	int s = 0,w = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
	return s * w;
}
bool comp(node a,node b)
{
	return a.x < b.x;
}
bool cmp(node a,node b)
{
	return a.y > b.y;
}
signed main()
{
	n = read(); z = read();
	for(int i = 1; i <= n; i++)
	{
		x = read(); y = read();
		int tmp = y-x;
		if(tmp >= 0)
		{
			a[++cnt1].id = i;
			a[cnt1].x = x;
			a[cnt1].y = y;
		}
		else 
		{
			b[++cnt2].id = i;
			b[cnt2].x = x;
			b[cnt2].y = y;
		}
	}
	sort(a+1,a+cnt1+1,comp);
	sort(b+1,b+cnt2+1,cmp);
	for(int i = 1; i <= cnt1; i++)
	{
		z -= a[i].x;
		if(z <= 0) { printf("NIE\n"); return 0;}
		z += a[i].y;
	}
	for(int i = 1; i <= cnt2; i++)
	{
		z -= b[i].x;
		if(z <= 0) { printf("NIE\n"); return 0;}
		z += b[i].y;
	}
	printf("TAK\n");
	for(int i = 1; i <= cnt1; i++) printf("%lld ",a[i].id);
	for(int i = 1; i <= cnt2; i++) printf("%lld ",b[i].id);
	return 0;
}

posted @ 2020-10-10 08:36  genshy  阅读(66)  评论(0编辑  收藏  举报