题目链接:http://poj.org/problem?id=3104

Drying
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 18378   Accepted: 4637

Description

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
5

Sample Output

sample output #1
3 sample output #2
2

Source

Northeastern Europe 2005, Northern Subregion
 
 
 
 
题解:
1.二分时间。
2.枚举每一件衣服,然后判断在限制的时间内是否能将所有时间烘干。
 
 
问:怎么判断?
 
思维一:模拟过程(即以时间为线程),每次拿一件进行“试烘烤”,如果这件衣服在剩余的时间内,能够自己风干,则把它扔在一边;否则,则需要对其进行烘烤,使得其经过烘烤后,在剩余的时间内能够自己风干,然后再把它扔一边。注意:在烘烤一件衣服的时候,其他未干的衣服也会蒸发水汽,所以需要记录当前时间,当拿到一件衣服时,就知道它还剩多少水分。
 
思维二:不模拟过程了,按照逻辑来做。假设当前二分到的时间为limit。 枚举每一件衣服,对于当前衣服:如果它可以在limit时间之内风干,扔在一边;否则,对其进行烘烤,使得其经过烘烤后,能够在“除烘烤时间的剩余时间”内自己风干,既可以扔在一边。对每一件衣服的烘烤时间求和,如果和小于等于limit,则limit合法,否则不合法。实际上,把思维一的代码稍微做一下变形,就可以得到思维二的代码。
 
 
过程中出现的一些错误:
1.在写思维一的test()函数时, 直接修改了原始数组,导致下一次调用test()的时候,数据已不是原来的数据了,应该开多个tmp[]数组,作为原始数组的副本,然后直接对tmp[]进行修改。(这个错误找了好久,而且前不久也犯了一次,心塞, 以此为鉴!!)
2.由于答案最大仅为1e9,在int范围内,所以就认为过程中不会出现溢出。但在test()函数内,time的值却可能会超出int, 因为a[i]<=1e9, n<=1e5,假如输入的k是2,且又不在time出现超出limit的时候直接返回, 而让其一直累加到最后,那就会溢出了。所以,在test()函数内,如果一旦出现“不可能”或“肯定能”就直接返回,而不要放任其继续操作,直到最后才返回,以造成预想不到的后果。
 
 
 
思维一错误代码:
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 1e5+; int n, k, a[MAXN]; bool test(int mid)
{
int time = , left = mid;
for(int i = n; i>=; i--)
{
a[i] -= time; // a[i]的值已经发生改变了!!!!!! 应该另开一个数组用于操作,以保证原始数值不被修改
if(a[i]<=left) continue;
int t = (a[i]-left)/(k-);
if((a[i]-left)%(k-)) t++;
time += t;
left -= t;
if(left<) return false;
}
return true;
} int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i = ; i<=n; i++)
scanf("%d", &a[i]);
scanf("%d", &k);
sort(a+, a++n);
if(k==)
{
printf("%d\n", a[n]);
continue;
} int l = , r = a[n];
while(l<=r)
{
int mid = (l+r)>>;
if(test(mid))
r = mid - ;
else
l = mid + ;
}
printf("%d\n", l);
}
}
思维二正确代码:
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 1e5+; int n, k, a[MAXN];
int tmp[MAXN]; bool test(int mid) //模拟过程
{
//time为当前时间, left为剩余时间, time与left之和恒为mid
int time = , left = mid;
memcpy(tmp, a, sizeof(tmp)); //!!!!!!
for(int i = n; i>=; i--)
{
tmp[i] -= time; //过了多长时间, 就风干了多少水。
if(tmp[i]<=left) continue; //如果剩下的时间可以让这件衣服完全风干, 则跳过;否则下一步
int t = (tmp[i]-left)/(k-); //t为使得这件衣服可以风干的最少烘干次数
if((tmp[i]-left)%(k-)) t++; //向上取整
time += t; //更新当前时间和剩余时间
left -= t;
if(left<) return false; //如果超额,则不能满足条件
}
return true;
} int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i = ; i<=n; i++)
scanf("%d", &a[i]);
scanf("%d", &k);
sort(a+, a++n);
if(k==) //当k为1时, 烘干机没用了, 全部自己风干。
{
printf("%d\n", a[n]);
continue;
} int l = , r = a[n];
while(l<=r)
{
int mid = (l+r)>>;
if(test(mid))
r = mid - ;
else
l = mid + ;
}
printf("%d\n", l);
}
}
思维二:
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 1e5+; int n, k, a[MAXN]; bool test(LL limit)
{
int sum = ;
for(int i = n; i>=; i--)
{
if(a[i]<=limit) continue; //直接风干
int t = (a[i]-limit)/(k-); //t为使得这件衣服可以风干的最少烘干次数
if((a[i]-limit)%(k-)) t++; //向上取整
sum += t; //时间累加
if(sum>limit) return false; //超过时间限制, 退出
}
return true; //满足条件
} int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i = ; i<=n; i++)
scanf("%d", &a[i]);
scanf("%d", &k);
sort(a+, a++n);
if(k==) //当k为1时, 烘干机没用了, 全部自己风干。
{
printf("%d\n", a[n]);
continue;
} int l = , r = a[n];
while(l<=r)
{
int mid = (l+r)>>;
if(test(mid))
r = mid - ;
else
l = mid + ;
}
printf("%d\n", l);
}
}
 

POJ3104 Drying —— 二分的更多相关文章

  1. POJ3104 Drying(二分查找)

    POJ3104 Drying 这个题由于题目数据比较大(1 ≤ ai ≤ 109),采用贪心的话肯定会超时,自然就会想到用二分. 设C(x)为true时表示所用时间为X时,可以把所有的衣服都烘干或者自 ...

  2. POj3104 Drying(二分)

    Drying Time Limit: 2000MS Memory Limit: 65536K Description It is very hard to wash and especially to ...

  3. POj-3104 Drying 二分+贪心

    题目大意:有n件湿的衣服,每件衣服都有相应的湿度,每分钟每件衣服的湿度减1(除了在烘干机里的衣服),现在有一个烘干机,烘干机一分钟可以让一件衣服的湿度降低k,问至少要花多少分钟才能使每件衣服的湿度为0 ...

  4. poj3104 Drying(二分最大化最小值 好题)

    https://vjudge.net/problem/POJ-3104 一开始思路不对,一直在想怎么贪心,或者套优先队列.. 其实是用二分法.感觉二分法求最值很常用啊,稍微有点思路的二分就是先推出公式 ...

  5. Drying poj3104(二分)

    Drying Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7916   Accepted: 2006 Descriptio ...

  6. POJ 3104 Drying(二分答案)

    题目链接:http://poj.org/problem?id=3104                                                                  ...

  7. POJ3104 Drying 2017-05-09 23:33 41人阅读 评论(0) 收藏

    Drying Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15604   Accepted: 3976 Descripti ...

  8. POJ3104 Drying

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13703   Accepted: 3527 Description It i ...

  9. POJ 3104 Drying [二分 有坑点 好题]

    传送门 表示又是神题一道 Drying Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9327   Accepted: 23 ...

随机推荐

  1. 关于时区、时间戳引起的bug理解

    时间戳定义:0时区1970年1月1日到现在的毫秒数,所以全世界同一时刻的时间戳都是一样的. 北京时间对应时间戳=unix(0时区对应时间的时间戳)-8*60*60*1000(8小时的毫秒数)----- ...

  2. uva 10515 规律打表

    Problem G Power et al. Input: Standard Input Output: Standard Output Finding the exponent of any num ...

  3. 文艺平衡树(bzoj 3223)

    Description   您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2  ...

  4. 洛谷 [P3205] 合唱队

    区间DP 手动模拟一下,我们发现本题就是一个左右加数的区间DP #include <iostream> #include <cstdio> #include <cstri ...

  5. Chapter 4-5

    1.切片对象  sequence[起始索引:结束索引:步进值] 对象身份的比较 is /is not 2.eval()参数是一个字符串, 可以把这个字符串当成表达式来求值. >>>x ...

  6. Python入门--3--操作符

    一.算数操作符 有:+.-.*././/.%.**(幂) a= 3; a = 3+1; #等同于a += 1  这相当与a加一 同样 也可以-.*././/          需要注意的是//是直接舍 ...

  7. Linux设置文件与Shell操作环境

    Shell设置文件读取流程 /etc/shells记录了Linux系统中支持的所有shell,默认使用bash.用户登入Linux系统时会获取到一个shell,具体获取到哪个shell与登录账号有关, ...

  8. Day 3 网络基础

    网络基础 一.什么是互联网协议及为何要有互联网协议 ? 互联网协议:指的就是一系列统一的标准,这些标准称之为互联网协议.互联网的本质就是一系列的协议,总称为‘互联网协议’(Internet Proto ...

  9. Java 新手的通病

    一:对算法和数据结构不熟悉 为什么我先拿“数据结构和算法”说事捏?这玩意是写程序最最基本的东东.不管你使用 Java 还是其它的什么语言,都离不开它.而且这玩意是跨语言的,学好之后不管在哪门语言中都能 ...

  10. T1229 数字游戏 codevs

    http://codevs.cn/problem/1229/ 题目描述 Description Lele 最近上课的时候都很无聊,所以他发明了一个数字游戏来打发时间.  这个游戏是这样的,首先,他拿出 ...