洛谷 P2440 木材加工【二分】

题目描述( 普及/提高- )

木材厂有一些原木,现在想把这些木头切割成一些长度相同的小段木头(木头有可能有剩余),需要得到的小段的数目是给定的。当然,我们希望得到的小段木头越长越好,你的任务是计算能够得到的小段木头的最大长度。木头长度的单位是 c m cm cm 。原木的长度都是正整数,我们要求切割得到的小段木头的长度也是正整数

例如有两根原木长度分别为 11 11 11 21 21 21,要求切割成到等长 6 6 6 段,很明显能切割出来的小段木头长度最长 5 5 5 .

输入格式

第一行是两个正整数 N N N K ( 1 ≤ N ≤ 100000 , 1 ≤ K ≤ 100000000 ) K(1 ≤ N ≤ 100000,1 ≤ K ≤ 100000000) K(1N1000001K100000000),N是原木的数目, K K K 是需要得到的小段的数目。

接下来的 N N N 行,每行有一个 1 1 1 100000000 100000000 100000000 之间的正整数,表示一根原木的长度。

输出格式

能够切割得到的小段的最大长度。如果连 1 c m 1cm 1cm 长的小段都切不出来,输出 0 0 0

输入输出样例
输入 #1

3 7
232
124
456

输出 #1

114

思路:这一道题是经典的二分题目。

一、代码1

#include 
#include 
using namespace std;
const int maxn = 100100;
int woods[maxn];
 
int main() { //小段木头越长越好 
	//给定的段数越大, 需要每段越短 //但是段数固定, 要让每段尽可能的长
	//即找到最大的那个满足k >= K的L, L再长就会让k < K 
	//或者找到第一个满足k < K的L, 答案就是L-1
	int N, K; //原木的数目 需要的小段数目
	cin >> N >> K;
	int l = 0, r = -1, mid; //对长度进行二分 
	for (int i = 0; i < N; ++i) {
		cin >> woods[i];
		r = max(r, woods[i]);
	} 
	while (l < r) {
		int k = 0; //每次按照二分的长度可以得到的小段的数目 
		mid = l + (r - l) / 2;
		if (mid < 1) {
			cout << 0;
			return 0;
		}
		for (int i = 0; i < N; ++i)
			k += (woods[i] / mid); 
		if (k < K) r = mid;
		else l = mid + 1; 
	}
	cout << l - 1;
	return 0;
}

二、代码2

#include 
#include 
using namespace std;
const int maxn = 100100;
int woods[maxn];
 
int main() {  
	//给定的段数越大, 需要每段越短 //但是段数固定, 要让每段尽可能的长
	//即找到最大的那个满足k >= K的L, L再长就会让k < K  
	int N, K; //原木的数目 需要的小段数目
	cin >> N >> K;
	int l = 0, r = -1, mid; //对长度进行二分 
	for (int i = 0; i < N; ++i) {
		cin >> woods[i];
		r = max(r, woods[i]);
	} 
	while (l < r) {
		int k = 0; //每次按照二分的长度可以得到的小段的数目 
		mid = (l + 1 + r) / 2; //如果执意使用找最后的最大的这个模板, 需要+1避免无限循环 
		if (mid < 1) {
			cout << 0;
			return 0;
		}
		for (int i = 0; i < N; ++i)
			k += (woods[i] / mid);  
		if (k >= K) l = mid;
		else r = mid - 1; 
	}
	cout << l;
	return 0;
} 

你可能感兴趣的:(#,二分,洛谷)