http://acm.buaa.edu.cn/problem/1389/
愤怒的DZY
【问题描述】
“愤怒的小鸟”如今已经是家喻户晓的游戏了,机智的WJC最近发明了一个类似的新游戏:“愤怒的DZY”。游戏是这样的:玩家有K个DZY,和N个位于不同的整数位置:X1,X2,…,XN的干草包。每一个DZY都可以站在某个位置:X 扔炸弹,扔完炸弹,这个DZY就会挂掉。扔炸弹的半径为R(且每次每个DZY扔炸弹的半径不变,都是R,而站的位置X可以改变),破坏范围为的X−R~X+R(即位置在X-R到X+R(含X-R,X+R)都会被炸掉)。现在给定DZY的个数K,和干草堆的位置:X1,X2,…,XN,问你最小的可以炸掉所有干草堆的半径R。
【输入说明】
第一行两个正整数N,K。接下来N行,每行一个数,依次是:X1,X2,…,XN。
【输出说明】
仅一行,代表最小的可以炸掉所有干草堆的半径R。
【样例输入】
7 2
20
25
18
8
10
3
1
【样例输出】
5
命题人:Hacker_WJC
学习了上题的最大值最小化,这题就很好解决了,数据n卡到10e6
对位置进行从小到大排序,枚举直径,不妨设最小直径为1,最大就是前后两点距离 a[n] - a[1],然后从a[1]开始枚举直径为mid是否可以,如果比a[i] + mid小就取下一个,否则cnt++,以该点为起点在判断
半径采用进一法输出,
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <iostream> 5 using namespace std; 6 const int MAX = 1000000 + 10; 7 int a[MAX]; 8 int n,k,maxn,minn; 9 void input() 10 { 11 minn = maxn = 0; 12 scanf("%d%d", &n, &k); 13 for(int i = 1; i <= n; i++) 14 { 15 scanf("%d", &a[i]); 16 } 17 sort(a + 1, a + n + 1); 18 minn = 1; 19 maxn = a[n] - a[1]; 20 } 21 bool is_ok(int mid) 22 { 23 bool ok = true; 24 int start = 1,End = 1; 25 int cnt = 1; 26 while(End <= n) 27 { 28 if(a[End] - a[start] <= mid) 29 { 30 End++; 31 } 32 else 33 { 34 cnt++; 35 if(cnt > k) 36 { 37 ok = false; 38 break; 39 } 40 start = End; 41 } 42 } 43 return ok; 44 } 45 int solve() 46 { 47 int x = minn, y = maxn; 48 49 while(x <= y) 50 { 51 int mid = (x + y) / 2; 52 if(is_ok(mid)) 53 y = mid - 1; 54 else 55 x = mid + 1; 56 } 57 return x; 58 } 59 int main() 60 { 61 input(); 62 int ans = solve(); 63 if(ans % 2 == 0) 64 printf("%d ", ans / 2 ); 65 else 66 printf("%d ", ans / 2 + 1); 67 }