题解 | #幻兽防御战#

幻兽防御战

https://www.nowcoder.com/practice/13a2e8a30e414f3f964548a834c26f7c

题目链接

幻兽防御战

题目描述

小红守卫遗迹,有 只怪兽冲向遗迹。第 只怪兽的初始距离为 ,移动速度为 ,其到达遗迹的时间为 。 小红每分钟只能发射一次弩箭。在第 分钟开始的瞬间(),小红可以消灭一只尚未到达遗迹的怪兽。 如果存在某只未被消灭的怪兽满足 ,则该怪兽会在小红准备好第 次射击(即第 分钟开始时)或之前抵达并摧毁遗迹,防守立即失败。 请计算小红在遗迹被摧毁前,最多能消灭多少只怪兽。

解题思路

这是一个典型的贪心问题。

  1. 计算到达时间: 对于每只怪兽,其到达遗迹的时间为

  2. 贪心策略: 为了尽可能多地消灭怪兽,小红应该优先消灭那些最早到达遗迹的怪兽。 我们将所有怪兽按照到达时间 从小到大进行排序。

  3. 模拟射击过程: 设定射击序号为 ,从 开始计数。

    • 次射击(在 时刻):检查当前到达时间最短的怪兽。如果 ,防御失败。否则消灭该怪兽。
    • 次射击(在 分钟开始时):检查此时未被消灭的怪兽中到达时间最短的那只(即排序后的第 只怪兽)。
    • 如果该怪兽的到达时间 ,说明在小红准备好这次射击时,怪兽已经到达了遗迹,防御失败。
    • 如果 ,则可以消灭这只怪兽,继续下一轮射击。
  4. 数值处理: 为了避免浮点数精度问题,比较 可以转化为整数比较:。 注意 可能会超过 ,因此在 C++ 和 Java 中需要使用 long longlong

代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 定义怪兽结构体
struct Monster {
    long long d, s;
};

// 按到达时间排序:d1/s1 < d2/s2 <=> d1 * s2 < d2 * s1
bool compareMonsters(const Monster& a, const Monster& b) {
    return a.d * b.s < b.d * a.s;
}

int main() {
    int n;
    cin >> n;
    vector<long long> d(n), s(n);
    for (int i = 0; i < n; ++i) cin >> d[i];
    for (int i = 0; i < n; ++i) cin >> s[i];

    vector<Monster> monsters(n);
    for (int i = 0; i < n; ++i) {
        monsters[i] = {d[i], s[i]};
    }

    // 按照到达时间升序排序
    sort(monsters.begin(), monsters.end(), compareMonsters);

    int ans = 0;
    for (int k = 0; k < n; ++k) {
        // 判断第 k 只怪兽是否在第 k 次射击前或射击瞬间到达
        // 比较 D_k / S_k <= k
        if (monsters[k].d <= (long long)k * monsters[k].s) {
            break;
        }
        ans++;
    }

    cout << ans << endl;

    return 0;
}
import java.util.*;

public class Main {
    // 怪兽类
    static class Monster {
        long d, s;
        Monster(long d, long s) {
            this.d = d;
            this.s = s;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long[] d = new long[n];
        long[] s = new long[n];
        for (int i = 0; i < n; i++) d[i] = sc.nextLong();
        for (int i = 0; i < n; i++) s[i] = sc.nextLong();

        List<Monster> monsters = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            monsters.add(new Monster(d[i], s[i]));
        }

        // 排序规则:d1/s1 < d2/s2 即 d1*s2 < d2*s1
        Collections.sort(monsters, (a, b) -> {
            long val1 = a.d * b.s;
            long val2 = b.d * a.s;
            return Long.compare(val1, val2);
        });

        int ans = 0;
        for (int k = 0; k < n; k++) {
            Monster m = monsters.get(k);
            // 检查 D_k <= k * S_k
            if (m.d <= (long) k * m.s) {
                break;
            }
            ans++;
        }
        System.out.println(ans);
    }
}
def solve():
    # 读取怪兽数量
    n = int(input())
    # 读取初始距离
    d_list = list(map(int, input().split()))
    # 读取移动速度
    s_list = list(map(int, input().split()))

    monsters = []
    for i in range(n):
        monsters.append((d_list[i], s_list[i]))

    # 按照到达时间 d/s 升序排序
    # Python 自动处理大整数,可以直接使用 d/s 排序或用 d * other_s 比较
    monsters.sort(key=lambda x: x[0] / x[1])

    ans = 0
    for k in range(n):
        d, s = monsters[k]
        # 判断第 k 只怪兽是否在第 k 分钟准备射击时或之前到达
        if d <= k * s:
            break
        ans += 1
    
    print(ans)

solve()

算法及复杂度

  • 算法:贪心算法 + 排序。
  • 时间复杂度:。主要开销在于对 只怪兽的到达时间进行排序。
  • 空间复杂度:。需要存储每只怪兽的初始距离和速度。
全部评论

相关推荐

不愿透露姓名的神秘牛友
03-05 00:46
点赞 评论 收藏
分享
03-04 07:14
门头沟学院 C++
后测速成辅导一两个月...:老板:都给工作机会了还想要工资,哪来这么多好事
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务