题目
分析
这道题是复合题:要用到“二分”和“贪心”。
贪心算法的核心在于:假定目前的放置距离是d
,那么以此距离——可以超过这个距离,因为牛棚的位置不是连续的——放牛,看看能否达到题目要求。
其代码如下:
bool canPlaceCows(const vector<int>& stalls, int C, int d)
{
int count = 1; // 放置第一头牛
int last_position = stalls[0]; // 第一头牛的位置
for (int i = 1; i < stalls.size(); ++i)
{
if (stalls[i] - last_position >= d) //第i个位置可以放一头牛
{
count++;
last_position = stalls[i]; // 更新最后放置的位置
if (count == C) // 成功放置所有牛
{
return true;
}
}
}
return false; // 无法放置所有牛
}
二分算法的核心在于:我们不知道合理的d
是多少,但直觉告诉我们d
总有个上限——超过这个上限后就肯定放不下了。所以很适合用二分法。
其代码如下:
while (left <= right)
{
int mid = left + (right - left) / 2; // 当前尝试的最小距离
if (canPlaceCows(stalls, C, mid))
{
result = mid; // 更新结果
left = mid + 1; // 尝试更大的最小距离
}
else
{
right = mid - 1; // 尝试更小的最小距离
}
}
需要注意的是,找到一个可行的距离(result
)后,不能终止执行,因为还可能找到一个更大的距离。所以我们保存当前可行的距离,并继续尝试更大的距离。
答案
思考
这道题目不难,但我还是放在这里,因为它有几个值得关注的地方:
- 结合了“二分”和“贪心”,而贪心是核心,二分作为辅助的手段。
- 但是,这题贪心的策略简单,而二分的策略需要有一些额外的考量。
算法一旦结合起来,威力无穷!