穿越沙漠的最少补给次数|豆包MarsCode AI刷题

121 阅读3分钟

问题描述

小U需要穿越一片广阔的沙漠,从起点到终点共有 (D) 公里。小U初始携带 (W) 升水,每行走 1 公里消耗 1 升水。沙漠中有多个绿洲,每个绿洲设有补给站,提供不同量的水。小U需要规划在哪些补给站停留,以保证整个旅途中水的供应,并希望通过最少的补给次数安全到达终点。如果无法到达终点,则输出 -1。

输入

  • d:终点距离起点的公里数。
  • w:小U初始携带的水量,单位为升。
  • position:一个数组,表示每个补给站距离起点的公里数。
  • supply:一个数组,表示每个补给站可以提供的水量,单位为升。

输出

  • 一个整数,表示小U到达终点所需的最少补给次数,如果无法到达终点则输出 -1。

测试样例

样例1:

输入:d = 10, w = 4, position = [1, 4, 7], supply = [6, 3, 5]
输出:1

样例2:

输入:d = 15, w = 3, position = [3, 6, 12], supply = [4, 5, 2]
输出:-1

样例3:

输入:d = 20, w = 10, position = [5, 15], supply = [8, 6]
输出:2

样例4:

输入:d = 7, w = 7, position = [], supply = []
输出:0

样例5:

输入:d = 25, w = 8, position = [7, 13, 18], supply = [7, 6, 5]
输出:3

解题思路

  1. 理解问题

    • 小U需要从起点走到终点,每走1公里消耗1升水。
    • 小U可以在补给站补充水,但需要规划最少的补给次数。
    • 如果小U在某一点的水量不足以到达下一个补给站或终点,则无法继续前进。
  2. 数据结构选择

    • 使用优先队列(最大堆)来存储每个补给站的水量。优先队列可以帮助我们快速获取当前可用的最大水量。
  3. 算法步骤

    • 初始化一个优先队列。

    • 遍历每个补给站:

      • 如果当前水量不足以到达下一个补给站,则从优先队列中取出最大水量进行补充,直到水量足够或优先队列为空。
      • 如果水量仍然不足,则无法到达终点,返回 -1。
      • 将当前补给站的水量加入优先队列。
    • 遍历结束后,如果水量不足以到达终点,则从优先队列中取出最大水量进行补充,直到水量足够或优先队列为空。

    • 如果最终水量仍然不足,返回 -1;否则,返回补给次数。

  4. 复杂度分析

    • 时间复杂度:O(n log n),其中 n 是补给站的数量。每次从优先队列中取最大值的操作是 O(log n),最多进行 n 次。
    • 空间复杂度:O(n),用于存储优先队列。

代码实现

#include <iostream>
#include <vector>
#include<unordered_map>
#include<queue>
using namespace std;
int solution(int d, int w, std::vector<int> position, std::vector<int> supply) {
    priority_queue<int> q;

    for(int i = 0; i < position.size(); i ++ ) {
        while(position[i] > w && w < d && q.size()) w += q.top(), q.pop();
        if(w < position[i]) break;
        q.push(supply[i]);
    }

    while(w < d && q.size()) w += q.top(), q.pop();
    if(w < d) return -1;

    return position.size() - q.size();
}

int main() {
    //  You can add more test cases here
    std::vector<int> testPosition = {170, 192, 196, 234, 261, 269, 291, 404, 1055, 1121, 1150, 1234, 1268, 1402, 1725, 1726, 1727, 1762, 1901, 1970};
    std::vector<int> testSupply = {443, 185, 363, 392, 409, 358, 297, 70, 189, 106, 380, 130, 126, 411, 63, 186, 36, 347, 339, 50};

    std::cout << (solution(10, 4, std::vector<int>{1, 4, 7}, std::vector<int>{6, 3, 5}) == 1) << std::endl;
    std::cout << (solution(2000, 200, testPosition, testSupply) == 5) << std::endl;

    return 0;
}