1 条题解
-
0
自动搬运
来自洛谷,原作者为

lgswdn_SA
舞台少女,每日进化中搬运于
2025-08-24 21:55:41,当前版本为作者最后更新于2020-10-20 22:34:00,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
LG4025 Bohater
传送门:https://www.luogu.com.cn/problem/P4025
题意
一开始有 点血。有 只怪物,每只怪物需要先消耗 点血,然后会恢复 点血。中途不能死掉。求一种可行的打怪顺序。
。
一个需要思考的贪心。
题解
首先一个很明显的贪心,先打打了可以回血的怪物,再打打了会掉血的怪物。
这个贪心的一个证明:假如一个回血怪物放在掉血怪物前面都没法打掉,那么放在掉血怪物后面更不可能打掉。
然后考虑回血怪物以及掉血怪物内部的安排贪心。
先考虑回血怪物。
- 对于那些 的回血怪物,直接打即可。
- 对于不能的,按照 从小到大排序。可以用调整法证明。
然后考虑掉血怪物。有两种理解方法。第一种还是用调整法来做。第二种我们可以发现,如果倒过来反向看,掉血怪物相当于回血怪物(从终局往回走, 作为掉血量, 作为回血量,每次血量都不能小于 ),于是我们按照倒叙视角的“掉血量”排序,即按照 排序。
排完序模拟即可。
#include<bits/stdc++.h> #define int long long #define rep(i,a,b) for(register int i=(a);i<=(b);i++) using namespace std; const int N=1e5+9; int n,sum,ans[N]; struct mons {int d,a,id;} a[N]; bool cmp(const mons &x, const mons &y) { if((x.a-x.d)*(y.a-y.d)<0) return x.a-x.d>0; else if(x.a-x.d<0) return x.a>y.a; else return x.d<y.d; } inline int read() { register int x=0, f=1; register char c=getchar(); while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-48,c=getchar();} return x*f; } signed main() { n=read(), sum=read(); rep(i,1,n) a[i].d=read(), a[i].a=read(), a[i].id=i; sort(a+1,a+n+1,cmp); rep(i,1,n) { sum-=a[i].d; if(sum<=0) return puts("NIE"), 0; ans[i]=a[i].id; sum+=a[i].a; } puts("TAK"); rep(i,1,n) printf("%lld ",ans[i]); return 0; }
- 1
信息
- ID
- 5058
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者