Divide and Conquer:River Hopscotch(POJ 3258)

时间:2023-03-08 23:53:07
Divide and Conquer:River Hopscotch(POJ 3258)

                Divide and Conquer:River Hopscotch(POJ 3258)

                  去掉石头

  题目大意:一群牛在河上的石头上跳来跳去,现在问你如何通过去掉M个石头,使得牛跳过石头的最短距离变得最大?

  这一题比较经典,分治法的经典,二分法可以很方便处理这个问题,我们只要明白比较函数这个东西就可以了。

  模板:

    while (……)
{
mid = (lb + rb) / ;
if (Judge_C(……))
else rb = mid;
}

  while判断条件可以根据是整形还是浮点型灵活变换,Judge_C就是比较函数,几乎所有的分治算法都可以这样归纳,我们只要找到合适的比较函数就可以了

  对于这题来说,他的比较函数可以这样看,我们先把石头去掉M个,然后在这些位置摆上,求最大的那个最短距离。

  这样一来,我们只用规定好上限就可以了(上限是length+1)

  

 #include <functional>
#include <iostream>
#include <algorithm> using namespace std; void Search(const int, const int);
bool Judge_C(const int, const int, const int); static int rock[];
static int Min_Step; int main(void)
{
int Length, M, Block_Sum;
while (~scanf("%d%d%d", &Length, &Block_Sum, &M))
{
for (int i = ; i <= Block_Sum; i++)
scanf("%d", &rock[i]);//rock储存的位置 rock[] = ;
rock[Block_Sum + ] = Length;//把开始的位置和结束的位置都存在数组里面 sort(rock, rock + Block_Sum + );
Search(M, Block_Sum);
}
return ;
} bool Judge_C(const int M, const int Block_Sum, const int min_distance)
{
int last = , pos = ; for (int i = ; i < Block_Sum - M; i++)
{
pos = last + ;
while (pos <= Block_Sum && rock[pos] - rock[last] < min_distance)
pos++;
if (pos == Block_Sum + )
return false;
last = pos;
}
return true;
} void Search(const int M, const int Block_Sum)
{
int lb = , rb = rock[Block_Sum + ] + , mid; while (rb - lb > )
{
mid = (lb + rb) / ;
if (Judge_C(M, Block_Sum, mid))
//判断C(x):把去掉M个石头看成去掉在这些位置放Block_Sum-M个石头
//注意上界是L+1,然后用二分逼近
lb = mid;
else rb = mid;
}
printf("%d\n", lb);
}

Divide and Conquer:River Hopscotch(POJ 3258)