分巧克力(二分)
题目地址: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 }