烘干衣服(二分策略)
It is very hard to wash and especially to dry clothes in winter. But Jane is a very smart girl. She is not afraid of this boring process. Jane has decided to use a radiator to make drying faster. But the radiator is small, so it can hold only one thing at a time.
Jane wants to perform drying in the minimal possible time. She asked you to write a program that will calculate the minimal time for a given set of clothes.
There are n clothes Jane has just washed. Each of them took ai water during washing. Every minute the amount of water contained in each thing decreases by one (of course, only if the thing is not completely dry yet). When amount of water contained becomes zero the cloth becomes dry and is ready to be packed.
Every minute Jane can select one thing to dry on the radiator. The radiator is very hot, so the amount of water in this thing decreases by k this minute (but not less than zero — if the thing contains less than k water, the resulting amount of water will be zero).
The task is to minimize the total time of drying by means of using the radiator effectively. The drying process ends when all the clothes are dry.
Input
The first line contains a single integer n (1 ≤ n ≤ 100 000). The second line contains ai separated by spaces (1 ≤ ai ≤ 109). The third line contains k (1 ≤ k ≤ 109).
Output
Output a single integer — the minimal possible number of minutes required to dry all clothes.
Sample Input
sample input #1 3 2 3 9 5 sample input #2 3 2 3 6 5Sample Output
sample output #1 3 sample output #2 2
翻译:
描述
洗衣服非常困难,特别是在冬天烘干衣服。但简是一个非常聪明的女孩。她不怕这个无聊的过程。Jane决定使用散热器来加快干燥速度。但是散热器很小,所以一次只能容纳一样东西。
Jane 希望在尽可能短的时间内进行干燥。她要求你编写一个程序,用于计算给定衣服的最短时间。
有N件衣服简刚洗过。他们每个人都在洗涤过程中喝了ai水。每分钟,每件东西中含有的水量就会减少一(当然,只有当东西还没有完全干燥时)。当所含的水量变为零时,布料变干并准备包装。
每分钟,Jane都可以选择一件东西在散热器上晾干。散热器非常热,所以这个东西的水量在这一分钟减少了k(但不小于零 - 如果这个东西含有少于k的水,则产生的水量将为零)。
任务是通过有效使用散热器来最大限度地减少干燥的总时间。当所有衣服都干燥时,干燥过程结束。
输入
第一行包含单个整数 n (1 ≤ n ≤ 100 000)。第二行包含由空格分隔的 ai(1 ≤ ai ≤ 109)。第三行包含 k(1 ≤ k ≤ 109)。
输出
输出单个整数 — 烘干所有衣服所需的最小可能分钟数。
思想:
1. 利用贪婪策略中的二分策略,求解得到最小的最长时间
2. 利用ceil()函数向上取整(变成大于等于的整数),注意处理对象是浮点数
3. 注意和上一个二分策略(愤怒的牛)对比,这里返回left,需要具体问题具体分析
解答:
/* ------------------------------------------------- Author: wry date: 2022/3/4 0:45 Description: test ------------------------------------------------- */ #include <iostream> #include <algorithm> #include <cmath> using namespace std; const int MAXN = 1e5+10; int water[MAXN]; bool Fun(int n,int k,int distance) { int sumTime=0; for (int i=0;i<n;i++) { if (water[i]>distance) { sumTime += ceil((water[i]-distance)*1.0/(k-1)); //向上取整ceil,必须为浮点数,否则没有效果,变得为>=自身的整数 } if (sumTime>distance) { return false; //出现错误就返回,提高效率 } } return true; } int main() { int n,k; cin >> n; for (int i=0;i<n;i++) { cin >> water[i]; } sort(water,water+n); //从小到大 cin >> k; if(k==1) { cout << water[n-1] << endl; } else { int left = 1; //可能的花时间的最小值 int right = water[n-1]; //可能的花时间的最大值 while (left<=right) { int middle = left + (right-left)/2; if (Fun(n,k,middle)) { right = middle-1; //说明时间充足,可以再测试时间小点的 } else { left = middle+1; //说明时间不够,需要测试时间更长些的 } } cout << left << endl; //参考最后一次如果正确。right会<left,而left为正确;如果错误,left变大,成为上一个成功的 } return 0; }