CSP-202303-2-垦田计划

CSP-202303-2-垦田计划

一、遇到问题:暴力枚举时间超限

  • k到最大天数maxDay,比较每次的总消耗量已有资源量,找到第一个总消耗量<=已有资源量对应的天数即为答案,这样做会导致时间超限

二、解决思路:二分查找优化

  1. 初始化搜索范围

    • left(最小可能天数)初始化为minDay,即题目中给定的最小天数要求。
    • right(最大可能天数)初始化为maxDay,这是通过遍历所有项目的耗时得到的最大值,理论上不可能有项目需要超过这个天数完成。
  2. 搜索过程

    • 计算中点:在每次迭代中,计算当前搜索范围的中点mid = (left + right) / 2。这个中点代表当前考虑的天数,用于检验是否所有项目都可以在这一天或之前完成,而不超过总资源限制
    • 检验条件:通过isEnough函数检查在mid天内是否能够满足所有项目的资源需求。isEnough函数通过累加所有尚未完成项目(即耗时大于当前天数mid的项目)的资源消耗,来判断是否超过了总资源量。
      • 如果isEnough(mid)返回true,说明在mid天内可以满足资源需求,因此可能还有更早的天数满足条件,所以将搜索范围的上界调整为mid - 1
      • 如果isEnough(mid)返回false,说明在mid天内不能满足资源需求,需要更多的天数,因此将搜索范围的下界调整为mid + 1
  3. 终止条件(重要)

    • left > right时,循环结束。left是满足条件的最小天数。这是因为最后一次迭代要么是因为找到了一个满足条件的mid,然后尝试更小的值(right = mid - 1),要么是因为找到了一个不满足条件的mid,然后尝试更大的值(left = mid + 1)。所以,当循环结束时,left指向的是第一个满足条件的天数。
#include 
#include 
using namespace std;

int n, resource, minDay, maxDay = -1;

bool isEnough(int currentDay, int* timeConsuming, int* resourceConsuming) {
    int totalConsumingResource = 0;
    for (int i = 0; i < n; i++) {
        if (timeConsuming[i] > currentDay) {
            totalConsumingResource += resourceConsuming[i] * (timeConsuming[i] - currentDay);
        }
    }
    return totalConsumingResource <= resource;
}

int main() {
    cin >> n >> resource >> minDay;
    int* timeConsuming = new int[n];
    int* resourceConsuming = new int[n];

    for (int i = 0; i < n; i++) {
        cin >> timeConsuming[i] >> resourceConsuming[i];
        maxDay = max(maxDay, timeConsuming[i]);
    }

    int left = minDay, right = maxDay;

    while (left <= right) {
        int mid = (left + right) / 2;
        if (isEnough(mid, timeConsuming, resourceConsuming)) {
            right = mid - 1;
        }
        else {
            left = mid + 1;
        }
    }
    cout << left;

    delete[] timeConsuming;
    delete[] resourceConsuming;
    return 0;
}

请添加图片描述

你可能感兴趣的:(算法,c++)