题目大意:一群牛在河上的石头上跳来跳去,现在问你如何通过去掉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 }
时间: 2024-10-06 09:00:13