poj3104二分

第一次写博客,希望给别人一些建议,同时也可以巩固自己的知识;

这道题目的题目我就不再赘述,在这里讲一下我自己的学习过程。一开始看到这道题目未想到用二分搜索,我用的是每次排序,取最大数a[n-1],a[n-1]则为用烘干机烘干,a[n-1]-k;重复这个过程,样例过了,但是TLE。。。。。。

题目来源:http://poj.org/problem?id=3104

后来我去网上找题解,看了很久才看懂,其中主要是公式和想法。个人认为只有大神级的人物才能推出这个公式,而且数学肯定特别好!接下来分享一下我自己的理解:


题目要求的是最短时间,时间的范围在( 1,max(a[i]) ),所以想到对时间进行二分搜索;mid = (l+r)/2;当a[i] < mid时,第i件衣服方式是自然晾干,其所需时间为 a[i]; 当a[i] > mid时,第i件衣服其所需的时间为:t = x + y  (x 为烘干机所用的时间,y为自然晾干所需的时间);可看出a[i] <= kx + y;联合式子(t = x+y),得出:x >= (a[i] - t)/(k-1); 把所有a[i] > mid其中使用烘干机所需的时间(向上取整)加起来 一定小于等于mid;

 AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<climits>
#include<algorithm> 
#include<cmath>


using namespace std;


int n;
long long a[100005],k;//一定要用 long long 否则会wa;

//根据 sum < mid 必须成立来理解二分

void erfen(long long l,long long r)
{
long long sum,mid;
while(l < r)
{
sum = 0;//每一次都要初始化为0
mid = (l+r)/2;
for(int i = 0 ; i < n; i++)
{
if(a[i] > mid)
{
sum += ceil((a[i] - mid)*1.0/(k-1));//向上取整,sum在累加的过程中会很大,所以用long long
}
}
if(sum > mid)
l = mid+1;
else
r = mid;//不能写成r = mid - 1; 手动算一遍你就会发现为什么

printf("%lld\n",r);
}


int main()
{
long long max;
while(scanf("%d",&n) != EOF)
{
max = 0;
for(int i = 0 ; i < n; i++)
{
scanf("%lld",&a[i]);
if(max < a[i])
max = a[i];
}
scanf("%lld",&k);
if(k == 1)//推出的式子中(k-1)作为分母,所以k==1,需要单独考虑
printf("%lld\n",max);
else
erfen(1,max);
}
  return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值