POJ 3104(二分)

来源:互联网 发布:旭日阳刚成名网络视频 编辑:程序博客网 时间:2024/05/21 02:33

怎么说呢这题,我觉得二分还是比较好想的,一开始时候直接暴力TLE,但是出乎意料的是思路是对的,用到了k-1,更神奇的是居然后来也想到了二分,但是不会处理,后来想想结合一开始的做就好了,

题目大意就是有n个衣服,每一个物品有一个权值ni,表示其有多少水,每一分钟自然烘干1,然后有一台洗衣机,可以更快的烘干,每一分钟为k,但是每次只能选一个衣服,求至少需要几分钟。

题解:二分,设至少需要x分钟,我们可以想一下,每一件衣服必然是自然烘干a分钟+洗衣机烘干b次,只不过a、b都可以取0。先把每个衣服的湿度减去x,因为不管怎么样x分钟后他肯定要烘干这么多,然后对于n个物品,从头扫一遍,只要不是0的,就说明他肯定用到洗衣机了,那么对于每一个用到洗衣机的衣服,他必然用到洗衣机的那么多次不会自然烘干,所以记x分钟过后他的湿度是left,那么他应该需要用到 left+(k-1) - 1 / k - 2次洗衣机,累积求和后和x相比是否够用和不够用。

其实这道题我的主要目的是锻炼一下二分,因为我发现我自己的二分老是进入死循环,不知道终止条件是什么,mid、left不知道是否需要+1,-1。不过做完这题后我有了更深的理解。

还有这道题会爆int。

#include <iostream>#include <iomanip>#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <algorithm>#define fuck() (cout << "------------------------------" << endl)using namespace std;const int maxn = 100000 + 5;long long  arr[maxn];int k,n;long long sam[maxn];bool judge(int x){    long long  cnt = 0;    for(int i=0; i<n; i++)    {        sam[i] = arr[i];        sam[i] -= x;        if(sam[i] < 0) sam[i] = 0;    }    if(k == 0)    {        for(int i=0; i<n; i++)            if(sam[i]) return false;        return true;    }    else    {        for(int i=0; i<n; i++)        {            cnt += (sam[i] + k - 1)/k;        }        if(cnt > x) return false;        return true;    }}int main(){    while(scanf("%d",&n)!=EOF && n)    {        memset(arr,0,sizeof(arr));        memset(sam,0,sizeof(sam));        int min_,max_;        for(int i=0; i<n; i++)        {            scanf("%lld",&arr[i]);        }        scanf("%d",&k);        k--;        long long  l = 0,r = 1000000010;// 2  9        long long   mid;        //int time = 0;        while(r-l>1)        {            //time++;            mid = (l+r)/2;//至少多少天            if(judge(mid)) r = mid;            else  l = mid;            //if(time == 100) cout << l << "  " << mid << "   " << r << endl;        }        printf("%lld\n",r);    }}


原创粉丝点击