一句话题意:
给你 (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
"); return 0;}
z += a[i].y;
}
for(int i = 1; i <= cnt2; i++)
{
z -= b[i].x;
if(z <= 0) { printf("NIE
"); return 0;}
z += b[i].y;
}
printf("TAK
");
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;
}