二分法poj3104题解

博客围绕烘干衣服问题展开,已知每件衣服有一定水分,不使用烘干机每分钟自然流失1单位水分,使用则每分钟流失K单位水分,且只有1台烘干机同时只能烘1件衣服。通过二分法求解烘干N件衣服的最短时间,给出了输入输出要求、样例及代码思路。
题意

每件衣服都有一定单位水分,在不适用烘干器的情况下,每件衣服每分钟自然流失1个单位水分,但如果使用了烘干机则每分钟流失K个单位水分,但是遗憾是只有1台烘干机,每台烘干机同时只能烘干1件衣服,请问要想烘干N件衣服最少需要多长时间?

输入

第一行输入N,表示有N件衣服,第二行输入N件衣服的水分ai,第三行表示烘干机每分钟烘干水分K
其中
1 ≤ N ≤ 100 000,1 ≤ ai ≤ 10^9,1 ≤ K≤ 10^9
输出
输出烘干N件衣服所需要的最短时间

样例输入

3
2 3 9
5

3
2 3 6
5

样例输出

3

2

个人理解,如果ai<mid,不用理他,可以自己晾干,如果ai>mid

				if((a[i] - mid ) % k == 0) {
					time += (a[i] - mid ) / k;
				}else {
					time += (a[i] - mid ) / k ;
					time ++;
				}

这里k是以前减过1的,可以自己想象一下,因为此时我将每个ai都减1了,不管用不用,时间过一个单位,都不用去算自己晾干的时间;除此之外还要向上取整,这个就好理解,比如7/5,应该是2,所以要加一

代码
import java.util.Arrays;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);
		
		int n = sc.nextInt();
		
		long [] a = new long [n];
		
		for(int i = 0; i < n; i++) {
			a[i] = Integer.parseInt(sc.next());
		}
		
		long k = sc.nextInt();
		
		long min = 0;
		long max = Integer.MAX_VALUE;
		
		if(k == 1) {
			Arrays.sort(a);
			System.out.println(a[a.length - 1]);
			return;
		}
		
		while(max - min > 1) {
			long mid = (min + max) / 2;
			if(f(mid, a, k - 1)) max = mid;
			else min = mid;
		}
		
		if(f(min, a, k - 1)) System.out.println(min);
		else System.out.println(max);
		
		sc.close();
		
	}
	
	public static boolean f(long mid, long [] a, long k) {
		
		long time = 0;
		
		for(int i = 0; i < a.length; i++) {
			if(time > mid) return false;
			if(a[i]> mid) {
				if((a[i] - mid ) % k == 0) {
					time += (a[i] - mid ) / k;
				}else {
					time += (a[i] - mid ) / k ;
					time ++;
				}
			}
		}
		
		return time <= mid;
		
	}
}
<think>嗯,用户问的是POJ3104用C++怎么写。首先我得回忆一下这道题的内容。POJ3104应该是一个算法题,可能涉及到二分查找或者贪心策略。不过具体的题目内容我得先确认一下。 POJ3104的题目大意是说,有n件衣服,每件衣服有ai滴水。现在用烘干机来烘干,每分钟可以选择一件衣服用烘干机,这样能烘干k滴水,而自然晾干每分钟只能烘干1滴。但烘干机一次只能处理一件衣服,其他衣服在那一分钟只能自然晾干。问最少需要多少分钟才能把所有衣服烘干。对吧? 那这个问题正确的解法应该是用二分查找。因为我们需要找到最小的分钟数,假设这个分钟数是mid。对于每件衣服,如果ai <= mid,那自然晾干就行。但如果ai > mid,就需要使用烘干机。这时候,计算用烘干机的次数x,满足ai - x*k <= mid -x,因为每次烘干机使用会多减少(k-1)滴水。所以x >= (ai - mid)/(k-1)。这里需要注意除法向上取整的问题。然后将所有需要的x加起来,如果总和超过mid,则mid太小,需要增大下界,反之可以尝试缩小上界。 不过这里有个特殊情况,当k=1的时候,因为k-1=0,这时候烘干机和自然晾干的效果一样,所以只能自然晾干,所需时间就是最大ai的值。 接下来,如何用C++实现呢?首先读取n,然后读取每个ai,接着读取k。然后进行二分查找。左边界是1,右边界是最大的ai。每次计算mid,然后判断是否可行。需要注意的是,当k=1的时候要单独处理,否则计算的时候会出现除以0的情况。 可能的代码结构大致如下: 读取输入,保存到数组a中。 计算最大的ai作为初始右边界。 如果k=1,直接输出max_ai。 否则,进行二分查找: left = 1, right = max_ai while left < right: mid = (left + right) / 2 计算总需要的烘干次数sum for每个ai: if ai > mid: sum += ceil((ai - mid) / (k - 1)) if sum <= mid: right = mid else: left = mid + 1 输出left 这里需要注意的是,计算(ai - mid)的时候,如果这个值是负数的话不需要处理。另外,ceil可以用整数运算来实现,例如 (ai - mid + k - 2) / (k -1)。 测试一下边界情况,比如当k=1的时候是否正确。另外,当所有ai都不需要烘干机的情况,比如所有ai都<=mid,这时候sum是0,所以可以满足。 还有可能出现的问题是在计算sum的时候,可能会溢出,但题目中的数据范围可能不会太大,所以用long long可能更安全。不过POJ的数据范围可能需要看题目具体要求。假设ai的范围在1e9的话,用long long更合适。 所以代码中变量sum应该用long long类型,防止累加时溢出。 综上,C++代码的大体框架应该是这样的。需要处理k=1的特殊情况,二分查找的条件判断,以及计算烘干次数时的向上取整。</think>POJ3104 题目要求用高效方法烘干衣服,下面详细介绍解题思路和C++实现: ### 题目分析 **问题描述**: - $n$件衣服,每件初始含水量为$a_i$ - 每分钟可选择**1件**衣服用烘干机(每秒减少$k$滴水),其余衣服自然晾干(每秒减少$1$滴) - 求烘干所有衣服的**最短时间** **关键观察**: 1. 烘干机使用策略影响总时间 2. 直接模拟会超时,需用**二分法**优化时间复杂度 ### 算法思路 1. **二分查找答案**: - 最小时间范围:$left=1$, $right=\text{max}(a_i)$ - 对每个候选时间$mid$,检查是否可行 2. **可行性判断**: - 对每件衣服$a_i$: - 若$a_i \leq mid$:自然晾干即可 - 若$a_i > mid$:需使用烘干机,计算最少使用次数 $$\text{烘干次数} \geq \lceil \frac{a_i - mid}{k-1} \rceil$$ - 总烘干次数$\leq mid$时才合法(每分钟最多用1次烘干机) ### C++代码实现 ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; typedef long long ll; int main() { int n, k; cin >> n; vector<int> a(n); for(int i=0; i<n; ++i) cin >> a[i]; cin >> k; int max_a = *max_element(a.begin(), a.end()); if(k == 1) { // 特殊情况处理 cout << max_a << endl; return 0; } ll left = 1, right = max_a; while(left < right) { ll mid = (left + right) / 2; ll sum = 0; for(int ai : a) { if(ai > mid) { // 计算ceil((ai - mid)/(k-1)) sum += (ai - mid + k-2) / (k-1); if(sum > mid) break; // 提前终止 } } if(sum <= mid) right = mid; else left = mid + 1; } cout << left << endl; return 0; } ``` ### 代码解析 1. **输入处理**:读取衣服数量和含水量 2. **特判$k=1$**:此时烘干机无效,直接输出最大含水量 3. **二分框架**: - 每次计算中点$mid$ - 统计所需烘干机总次数 - 根据总次数调整搜索区间 4. **关键计算**: - 使用整数技巧实现向上取整,避免浮点误差 - 提前终止循环优化效率 ### 复杂度分析 - **时间复杂度**:$O(n \log C)$,其中$C$为最大含水量 - **空间复杂度**:$O(n)$存储含水量数据 此解法能够高效处理题目中的大规模数据,通过二分将问题转化为可行性验证,避免了直接模拟的低效。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值