Divide and Conquer:River Hopscotch(POJ 3258)

                

                  去掉石头

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

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

  模板:

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

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

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

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

  

 1 #include <functional>
 2 #include <iostream>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 void Search(const int, const int);
 8 bool Judge_C(const int, const int, const int);
 9 
10 static int rock[50005];
11 static int Min_Step;
12 
13 int main(void)
14 {
15     int Length, M, Block_Sum;
16     while (~scanf("%d%d%d", &Length, &Block_Sum, &M))
17     {
18         for (int i = 1; i <= Block_Sum; i++)
19             scanf("%d", &rock[i]);//rock储存的位置
20 
21         rock[0] = 0;
22         rock[Block_Sum + 1] = Length;//把开始的位置和结束的位置都存在数组里面
23         
24         sort(rock, rock + Block_Sum + 2);
25         Search(M, Block_Sum);
26     }
27     return 0;
28 }
29 
30 bool Judge_C(const int M, const int Block_Sum, const int min_distance)
31 {
32     int last = 0, pos = 0;
33 
34     for (int i = 0; i < Block_Sum - M; i++)
35     {
36         pos = last + 1;
37         while (pos <= Block_Sum && rock[pos] - rock[last] < min_distance)
38             pos++;
39         if (pos == Block_Sum + 1)
40             return false;
41         last = pos;
42     }
43     return true;
44 }
45 
46 void Search(const int M, const int Block_Sum)
47 {
48     int lb = 0, rb = rock[Block_Sum + 1] + 1, mid;
49 
50     while (rb - lb > 1)
51     {
52         mid = (lb + rb) / 2;
53         if (Judge_C(M, Block_Sum, mid))
54             //判断C(x):把去掉M个石头看成去掉在这些位置放Block_Sum-M个石头
55             //注意上界是L+1,然后用二分逼近
56             lb = mid;
57         else rb = mid;
58     }
59     printf("%d\n", lb);
60 }

posted @ 2015-12-21 00:51  PhiliAI  阅读(228)  评论(0编辑  收藏  举报