题目地址:https://www.dotcpp.com/oj/problem1885.html

分巧克力(二分)_一维数组

 

分析:

我们知道,在1~100000之间的任何一个数x,将各个“大块的巧克力”按照边长为x的正方形进行切割,如果切割的块数大于等于K,就能够实现每个小朋友都有一份的目标。我们要找的是最大的那个x,

不妨记为maxX(如果最大值为maxX,那么1到maxX之间的任何数x都可以作为正方形巧克力的边长)。该题乍一看似乎与查找没关系,但是仔细分析,可以将原问题理解为:在1~100000之间寻找一个maxX,

使得将巧克力按照边长maxX进行切分,切分成的份数要大于等于K,而如果按照maxX+1进行切割,将不再能够切出K块。如果从1-100000逐个查找,那么肯定超时,所以采用二分查找。

那如何判断能否以mid为边长分割出大于等于K块正方形巧克力呢?假设n块巧克力的长和宽分别保存在两个一维数组H[100000]和W[100000]的n个元素里。

由于一块大小为H*W(长为H,宽为W)的巧克力,可以切割成的边长为mid的正方形巧克力的块数为:(H/mid)*(W/mid),所以n块巧克力所切割成的总块数cnt可以按照下面的方式计算出来:

int cnt = 0;
for(int i = 1; i<= n; i++)
{
cnt+= (H[i]/x)*(W[i]/x);
}

显然当cnt大于等于K时,就可以切割出能够分给小朋友的巧克力,否则就切割不出。

 

1 #include <iostream>
2 #include <cstring>
3
4 using namespace std;
5
6 int n, k, a[110000], b[110000];
7
8 bool ok(int x)
9 {
10 int cnt = 0;
11 for (int i = 1; i <= n; i++)
12 {
13 cnt += (a[i] / x)*(b[i] / x);
14 if (cnt >= k)
15 return true;
16 }
17
18 return false;
19 }
20
21 int main()
22 {
23
24 cin >> n >> k;
25 for (int i = 1; i <= n; i++)
26 cin >> a[i] >> b[i];
27
28 int l = 0;
29 int r = 100000;
30
31 while (l <= r) // 此处一定要有等号
32 {
33 int m = (l + r) / 2;
34 if (ok(m))
35 l = m + 1;
36 else
37 r = m - 1;
38 }
39 cout << l - 1 << endl;
40
41 return 0;
42 }