题目描述:
在一个2D横版游戏中,所有的怪物都是在X轴上的,每个怪物有两个属性X和HP,分别代表怪物的位置和生命值。
玩家控制的角色有一个AOE(范围攻击)技能,玩家每次释放技能可以选择一个位置x,技能会对[x-y,x+y]范围内的所有怪物造成1点伤害,请问,玩家最少需要使用多少次技能,才能杀死所有怪物,怪物血量清0即视为被杀死。
输入描述
输入第一行包含一个两个正整数n和y,分别表示怪物的数量和技能的范围。(1<=n<=100000)
接下来有n行,每行有两个正整数x和hp分别表示一只怪物的位置和血量。(1<=x,hp<=10^9)
输出描述
输出仅包含一个整数,表示最少使用的技能次数。
样例输入
3 5 1 10 10 5 22 3
样例输出
13
复盘:贪心
先对怪物从小到大排序,每次从消灭最左的怪物,在[最左怪物的位置,最左怪物位置 + 2 * y]区间的怪物也一起掉血。 然后再找下一个血量大于0的怪物,直到消灭所有怪物。
原理:你肯定需要消灭最左的怪物->消灭最左怪物的点肯定在[最左怪物位置,最左怪物位置+y]之间 -> 所以选择[最左怪物的位置,最左怪物位置 + 2 * y]区间的怪物也一起掉血,直到消灭所有怪物
package com.yyc.test;
import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
public class Test {
public static void main(String[] args) {
int n = 3, y = 5;
int[][] nums = new int[3][2];
nums[0][0] = 1;
nums[0][1] = 10;
nums[1][0] = 10;
nums[1][1] = 5;
nums[2][0] = 22;
nums[2][1] = 3;
test(nums, n, y);
}
public static int test(int[][] nums, int n, int y) {
if (n == 1) {
return nums[0][1];
}
Arrays.sort(nums, (a, b) -> {
if (a[0] == b[0]) {
return a[1] - b[1];
}
return a[0] - b[0];
});
Deque<Integer> deque = new LinkedList<>();
int index = 0;//杀死野怪个数
deque.offer(nums[index][1]); //生命值入队
int j = index + 1; // 范围开始位置
int len = nums[j - 1][0] + 2 * y; //技能会对[x-y,x+y]范围内的所有怪物造成1点伤害,相当于站在【i,len】的中间
while (j < n && nums[j][0] <= len) {
deque.offer(nums[j][1]); //生命值入队
j++;
}
int res = 0;
while (!deque.isEmpty()) {
Integer val1 = deque.poll(); // 队列内第一个野怪的生命值
if (val1 <= 0) {//说明该野怪在上一次已经被杀死,重新计算攻击范围
index++; // 范围开始位置,假设每次只删除一个
j = index + 1;
if (j < n) {
len = nums[j - 1][0] + 2 * y; //技能会对[x-y,x+y]范围内的所有怪物造成1点伤害,相当于站在【i,len】的中间
while (j < n && nums[j][0] <= len) {
deque.offer(nums[j][1]); //生命值入队
j++;
}
}
if (deque.isEmpty() && j < n) {//说明队列内的已经全部被删除,且后面的不在之前的范围攻击内,需重新入队;
index = j;
deque.offer(nums[index][1]); //生命值入队
j = index + 1;
if (j < n) {
len = nums[j - 1][0] + 2 * y; //技能会对[x-y,x+y]范围内的所有怪物造成1点伤害,相当于站在【i,len】的中间
while (j < n && nums[j][0] <= len) {
deque.offer(nums[j][1]); //生命值入队
j++;
}
}
}
} else {
res += val1;
int size = deque.size();
for (int i = 0; i < size; i++) {
Integer poll = deque.poll();// 先删除,再按序重新入队
deque.push(poll - val1);// 减去删除第一个元素所用的共计次数
}
}
}
System.out.println(res);
return res;
}
}