题目描述
入职后,导师会请你吃饭,你选择了火锅。 火锅里会在不同时间下很多菜. 不同食材要煮不同的时间,才能变得刚好合适。 你希望吃到最多的刚好合适的菜,但你的手速不够快,用 m 代表手速,每次下手捞菜后至少要过 m 秒才能再捞(每次只能捞一个)。 那么用最合理的策略,最多能吃到多少刚好合适的菜?
输入描述
第一行两个整数 n,m,其中 n 代表往锅里下的菜的个数,m 代表手速。 (1<n,m< 1000)
接下来有 n 行,每行有两个数 x,y 代表第 x 秒下的菜过 y 秒才能变得刚好合适。
(1<x,y< 1000)。
输出描述
输出一个整数代表用最合理的策略,最多能吃到刚好合适的菜的数量。
用例
输入
3 2
1 2
2 1
3 2
输出
2
ps:
往锅里下的菜的个数3,手速2;
第1秒的时候下入菜品1,2秒后熟了;
第2秒的时候下入菜品2,1秒后熟了;
第3秒的时候下入菜品3,2秒后熟了;
第一种菜品和第二种菜品只能吃到一种,第三种菜品可以吃到;
输出 2
思路
这个算法的核心思想是贪心算法,即在每一步都做出局部最优的选择,从而希望最终得到全局最优解。在这个问题中,局部最优的选择是尽可能早地捞那些变刚好合适的菜,这样可以留出更多的时间来捞后面的菜。以下是详细的解释:
为什么这样可以吃到最多的菜?
-
按变刚好合适的时间排序:
- 我们首先计算每个菜变刚好合适的时间
x + y,然后按x+y时间升序排序。这样做是为了确保我们总是先考虑最早变刚好合适的菜。
- 我们首先计算每个菜变刚好合适的时间
-
尽可能早地捞菜:
- 通过按
x + y时间排序,我们可以确保每次捞菜时,选择的是当前时间之前最早变刚好合适的菜。这样可以最大化我们捞菜的机会,因为如果我们错过了早期的菜,后面的时间可能会被浪费。
- 通过按
-
手速限制:
- 每次捞菜后,手速
m会限制我们再次捞菜的时间。因此,我们需要确保在满足手速限制的前提下,尽可能多地捞到菜。
- 每次捞菜后,手速
-
维护上一次捞菜的时间:
- 我们用一个变量
last_time来记录上一次捞菜的时间。每次捞菜后,更新last_time为当前菜的x + y时间。这样可以确保我们不会违反手速限制。
- 我们用一个变量
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int n, m;
cin >> n >> m;
vector<int> food(n);
for (int i = 0; i < n; i++)
{
int x, y;
cin >> x >> y;
food[i] = x + y;
}
sort(food.begin(), food.end());
// 第一筷子肯定要吃到
int last_time = food[0];
int count = 1;
for (int i = 1; i < n; i++)
{
if (last_time + m <= food[i])
{
count++;
last_time = food[i];
}
}
cout << count << endl;
return 0;
}