题目链接: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. PHP文件上传设置和处理(多文件)

    <!--upload.php文件内容--><?phpheader("Content-Type:text/html;charset=utf-8");/* //原来$ ...

  2. Nk 1214 Relatives(欧拉函数)

    Time Limit: 1500 ms    Memory Limit: 10000 kB   Total Submit : 234 (77 users)   Accepted Submit : 10 ...

  3. 解决U3D4.1.5或以上无法启动MONODEV的方法

    通常会报这样的错误 System.EntryPointNotFoundException: Unable to find an entry point named 'gtksharp_list_get ...

  4. laravel控制器

    //访问MemberController下的info的方法 //方法一//访问路径http://localhost/Laravel/public/member/infoRoute::get('memb ...

  5. websocket笔记

    本文为原创,转载请注明出处: cnzt       文章:cnzt-p http://www.cnblogs.com/zt-blog/p/6742746.html websocket -- 双向通信网 ...

  6. Java8 本地DateTime API

    原文:http://www.yiibai.com/java8/java8_localdateapi.html 使用Java8,新的日期时间API引入覆盖旧的日期时间API的以下缺点. 非线程安全 - ...

  7. 【Spring boot】【gradle】idea新建spring boot+gradle项目

    在此之前,安装了idea/jdk/gradle在本地 ===================================== gradle怎么安装:http://www.cnblogs.com/s ...

  8. TongWeb

    TongWeb 编辑 本词条缺少名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! 作为国内领先的中间件开发商,是国内最早研究J2EE技术和开发应用服务器产品的厂商.应用服务器TongWe ...

  9. git log 查看版本演变历史

    1.查看git操作历史 $ git log  #git 查看git操作历史 $ git log  --oneline #git 简洁的查看git变更记录 $ git log -n4  --onelin ...

  10. cocos2d-x-3.6 引擎概述

    cocos2d-x是一个游戏开发引擎,从公布到如今也有五六年了,一路看它慢慢壮大.它是如今应用最多的开源2d引擎,没有之中的一个,据说已经占据90%的市场,所以.对于想从事游戏开发的童鞋来说还是有必要 ...