Drying(二分,贼坑)

题目链接:https://cn.vjudge.net/contest/279225#problem/E
题目大意:就是有n件刚洗了的衣服,然后每件衣服有a[i]的水,自然风干可以一分钟少1个水量,用暖气烘干一分钟可以少k个水量,现在问使所有的衣服都晾干最少要用多长的时间。
思路:首先说这个,使最小值,所以右区间是可行解,左区间是不可行解。然后判断条件:判断x嘛,如果衣服的水量小于等于x,那么就可以自然风干了,如果衣服的水量大于x,那就不能自然风干。现在我们假设这个衣服上的水量大于x的衣服最少需要nuan的时间在暖气上烘干,然后需要自然风干的水量就是x-nuan;自然风干后剩下的水是:a[i]-(x-nuan),这些水需要暖气烘干,也就是nuan*k;
也就是有下面的式子:

a[i]-(x-nuan)=nuan*k

可以得到:

nuan=(a[i]-x)/(k-1)

这个式子取等的话就是每件水量大于x的衣服需要在暖气上烘干的时间,但是我们不可能用小数,所以我们要向上取整,所以这些时间加起来如果小于等于x就是可行的。
这里额外说一下就是,其实这个方法我理解了很久,我不知道为什么要做这样的假设,后来我想明白了,因为水量大于x的衣服自然风干没办法完全晾干,所以我们要借助暖气烘干,但是这个过程不是所有的水量都放在暖气上烘干的,可能还会有自然晾干的一部分,所以我们这里算的暖气上烘干的时间实际上是它最少要在暖气上烘干多久,只要这些两种时间加起来小于等于x就可以,因为可能不止有一件水量大于x的衣服,所以这儿要理解一下吧,也可能只有我才会纠结这种东西,因为我看别人的博客的时候都没有看到多少分析什么的,人家大佬都能明白吧,我不能理解,所以我这道题已经做了两天了……

#include<stdio.h>
#include<math.h>
#define INF 100005
long long a[INF];
long long n,k;
bool judge(long long x)
{
    long long sum=0;
    for(long long i=0; i<n; i++)
    {
        if(a[i]>x)
        {
            sum+=(long long)ceil((double)(a[i]-x)/(k-1));//这里是三种向上取整的方法,哪种都ok
            //sum+=(a[i]-x+k-2)/(k-1);
//            sum+=(a[i]-x)/(k-1);
//            if((a[i]-x)/(k-1))
//                sum++;
        }
    }
    return sum>x;
}
int main()
{
    while(~scanf("%lld",&n))
    {
        long long max_,min_,mid;
        max_=0;
        min_=0;
        for(long long i=0; i<n; i++)
        {
            scanf("%lld",&a[i]);
            if(max_<a[i])
                max_=a[i];
        }
        scanf("%lld",&k);
        if(k==1)
        {
            printf("%lld\n",max_);
            continue;
        }
        else
        {
            while(max_-min_>=0)
            {
                mid=(max_+min_)/2;
                if(judge(mid))
                    min_=mid+1;
                else
                    max_=mid-1;
            }
            printf("%lld\n",min_);
        }
    }
    return 0;
}

下面这种也是可以的:

else
        {
            while(max_-min_>1)
            {
                mid=(max_+min_)/2;
                if(judge(mid))
                    min_=mid;
                else
                    max_=mid;
            }
            printf("%lld\n",max_);
        }

下面这种就是我换了这种方法之后一直一直一直一直T的写法,我真的是fo,为什么会T,真的很无语好不好,然后后来我就很纳闷,我就直接贴了其他人博客上的代码上去,A了……我就更无语了,明明思路是一样的,怎么会T。然后我就又认真看了一下,然后发现题目上不是有

sample input #1
3
2 3 9
5

sample input #2
3
2 3 6
5
sample output #1
3

sample output #2
2

它给的输入输出是这样的,然后我就认为它要这样输入输出,但是我贴的那个别人的代码是没有的,所以我就把它删了,再交,出现了"Output Limit Exceeded",这什么鬼哦,当然就百度,然后就看嘛,大概意思就是说出现了死循环输出……然后后面还附了一个"Time Limit Exceeded"说是出现死循环嘛,然后就立马意识到自己的while循环条件写的是ture,难道是不行的?然后我就改了,改了之后立马就A了……但是之后呢我又重新精简了下代码然后贴上去,结果是wa了……这就很尴尬了,一模一样的写法,然后后来我就对着a了的,改我错的那份代码,最后改成一模一样的了还是wa……我就无语了,简直无语……然后后来就找学长,我问他是不是vj交了几发之后就不能交了,他说不是,然后我就给他说了这个问题,然后他帮我找不同,最后结果是少了个"%"!!!输出的时候忘记了这个!!!我也是……醉了,还被他凶了一顿,什么不要老是怀疑vj,认真点什么之类的,呜呜呜,我也很无语好不好……好吧,是我删减的时候删多了……呜呜呜,好弱呀

下边这个就是我开始写的,然后就一直T的那个……,我是记住了………………

#include<stdio.h>
#include<math.h>
#define INF 100005
typedef long long ll;
const char str[100]= {"sample output #"};
ll a[INF];
ll n,k;
ll max_,min_,mid;
ll judge(ll x)
{
    ll sum=0;
    for(ll i=0; i<n; i++)
    {
        if(a[i]>x)
        {
            sum+=(ll)ceil((double)(a[i]-x)/(k-1));
            //sum+=(a[i]-x+k-2)/(k-1);
        }
    }
    return sum>x;
}
int main()
{
    while(true)
    {
        ll d;
        while(getchar()!='#');
        scanf("%lld",&d);
        scanf("%lld",&n);
        max_=0;
        min_=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)
            {
                printf("%s%lld\n%lld\n",str,d,max_);
                continue;
            }
        else
        {
            while(max_>=min_)
            {
                mid=(max_+min_)/2;
                if(judge(mid))//不可行往右取
                    min_=mid+1;
                else//可行,但不一定最优,往左取
                    max_=mid-1;
            }
            printf("%s%lld\n%lld\n",str,d,min_);
        }
    }
    return 0;
}


其实我开始不是这么做的,我开始就是特别特别特别最最最常规的方法,二分加贪心嘛,先从衣服水量最大的开始烘干,一分钟过后,烘干的衣服水量-k,自然风干的就-1,然后再找水量最大的衣服,一直循环到所有的衣服水量都为0。然后就超时了……

#include<stdio.h>
#include<ctype.h>
#define INF 100005
const char str[100]= {"sample output #"};
int a[INF];
int n,k;
int tsum;
int max_,min_,mid;
int MAX(int arr[],int num)
{
    int ans=0;
    int ansi=0;
    for(int i=0; i<num; i++)
    {
        if(ans<arr[i])
        {
            ans=arr[i];
            ansi=i;
        }
    }
    return ansi;
}
int SUM(int arr[],int num)
{
    int ans=0;
    for(int i=0; i<num; i++)
    {
        if(arr[i]>0)
        {
            ans++;
        }
    }
    return ans;
}
int fun(int x)
{
    while(SUM(a,n))
    {
        for(int i=0; i<n; i++)
        {
            if(i!=MAX(a,n)&&a[i]>0)
                a[i]--;
            else
                a[i]-=k;
        }
        tsum++;
    }
    return tsum>x;//这是不可行的
}
int main()
{
    while(true)
    {
        int d;
        while(getchar()!='#');
        scanf("%d",&d);
        scanf("%d",&n);
        for(int i=0; i<n; i++)
        {
            scanf("%d",&a[i]);
        }
        scanf("%d",&k);
        tsum=0;
        max_=a[MAX(a,n)];
        min_=0;
        while(max_>=min_)
        {
            mid=(max_+min_)/2;
            if(fun(mid))//不可行往右取
                min_=mid+1;
            else//可行,但不一定最优,往左取
                max_=mid-1;
        }
        printf("%s%d\n%d\n",str,d,min_);

    }
    return 0;
}

你都无法想象我已经疯狂到什么程度,开始不是没用上面说的那种方法,然后就尽量改了能减少运算的就减少运算,我甚至后来改了指针,但是由于不怎么会用所以一直报错,我就放弃了,反正就是各种怀疑,然后还是各种T…………醉了
尤其是我后来改我那个开始A,后来wa的那个的时候,已经到达疯狂了,我怀疑是不是不能用typedef long long ll;是不是前边if都已经continue了,后边还是要加else;是不是不能把max_,min_,mid放全局……反正就是各种改,后来改的和我A了的那份所有格式是一样的,就连缩进都是一样的,它还是wa了,然后我就是真的fo了,最后知道是少了个%,我就更fo了,天那,真可怕……呜呜呜,我好弱哦……今天上午又只弄这个了………………

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值