• Google Code Jam Round 1A 2015 Problem B. Haircut 二分


    Problem
    
    You are waiting in a long line to get a haircut at a trendy barber shop. 
    The shop has B barbers on duty, and they are numbered 1 through B.
    It always takes the kth barber exactly Mk minutes to cut a customer's hair,
    and a barber can only cut one customer's hair at a time. Once a barber
    finishes cutting hair, he is immediately free to help another customer. While the shop is open, the customer at the head of the queue always goes
    to the lowest-numbered barber who is available. When no barber is available,
    that customer waits until at least one becomes available. You are the Nth person in line, and the shop has just opened. Which barber
    will cut your hair? Input The first line of the input gives the number of test cases, T. T test cases
    follow; each consists of two lines. The first contains two space-separated
    integers B and N -- the number of barbers and your place in line.
    The customer at the head of the line is number 1, the next one is number 2,
    and so on. The second line contains M1, M2, ..., MB. Output For each test case, output one line containing "Case #x: y",
    where x is the test case number (starting from 1) and y is the number of the barber who will cut your hair. Limits 1 ≤ T ≤ 100. 1 ≤ N ≤ 109. Small dataset 1 ≤ B ≤ 5. 1 ≤ Mk ≤ 25. Large dataset 1 ≤ B ≤ 1000. 1 ≤ Mk ≤ 100000. Sample Input Output 3 2 4 10 5 3 12 7 7 7 3 8 4 2 1 Case #1: 1 Case #2: 3 Case #3: 1 In Case #1, you are the fourth person in line, and barbers 1 and 2 take 10 and 5 minutes,
    respectively, to cut hair. When the shop opens, the first customer immediately has the
    choice of barbers 1 and 2, and she will choose the lowest-numbered barber, 1. The second
    customer will immediately be served by barber 2. The third customer will wait since there
    are no more free barbers. After 5 minutes, barber 2 will finish cutting the second
    customer's hair, and will serve the third customer. After 10 minutes, both barbers 1 and
    2 will finish; you are next in line, and you will have the choice of barbers 1 and 2, and will choose 1.

      

    题目很简短,也很好理解。

    如果用最朴素的方法,不管是暴力还是用 STL 里的 SET ,都需要从 1 遍历到 N (10^9) 那么肯定是不行的

    我想到了既然人数那么多说不定有规律可循,过了小数据, TLE 了大数据... 【姿势不对啊

    //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
    #include <stdio.h>
    #include <iostream>
    #include <fstream>
    #include <cstring>
    #include <cmath>
    #include <stack>
    #include <string>
    #include <map>
    #include <set>
    #include <list>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #define Max(a,b) (((a) > (b)) ? (a) : (b))
    #define Min(a,b) (((a) < (b)) ? (a) : (b))
    #define Abs(x) (((x) > 0) ? (x) : (-(x)))
    #define MOD 1000000007
    #define pi acos(-1.0)
    
    using namespace std;
    
    typedef long long           ll      ;
    typedef unsigned long long  ull     ;
    typedef unsigned int        uint    ;
    typedef unsigned char       uchar   ;
    
    template<class T> inline void checkmin(T &a,T b){if(a>b) a=b;}
    template<class T> inline void checkmax(T &a,T b){if(a<b) a=b;}
    
    const double eps = 1e-7      ;
    const int M = 1100011*2      ;
    const ll P = 10000000097ll   ;
    const int MAXN = 10900000    ;
    const int INF = 0x3f3f3f3f   ;
    
    int B, N;
    int a[1200], cur[1200];
    int ans[1000000];
    
    int main(){
        std::ios::sync_with_stdio(false);
        int i, j, t, k, u, v, numCase = 0;
    
        ofstream fout ("B-large-practice.out");
        ifstream fin ("B-large-practice.in");
    
        fin >> t;
        int T = t;
        for (T = 1; T <= t; ++T) {
            cout << T << endl;
            fin >> B >> N;
            for (i = 1; i <= B; ++i) {
                fin >> a[i];
            }
            memset (cur, 0, sizeof (cur));
            int flag = 1;
            int sum = 0;
            for (i = 1; i < N; ++i) {
                cur[flag] += a[flag];
                ans[sum++] = flag;
                int MIN = INF;
                for (j = 1; j <= B; ++j) {
                    if (cur[j] < MIN) {
                        MIN = cur[j];
                        flag = j;
                    }
                }
                for (j = 1; j < B; ++j) {
                    if (cur[j] ^ cur[j + 1]) {
                        break;
                    }
                }
                if (j == B) {
                    break;
                }
            }
            if (i == N) {
                flag = 1;
                for (i = 2; i <= B; ++i) {
                    if (cur[i] < cur[flag]) {
                        flag = i;
                    }
                }
            } else {
                if (N % sum == 0) {
                    flag = ans[sum - 1];
                } else {
                    flag = ans[N % sum - 1];
                }
            }
    
            fout << "Case #" << ++numCase << ": " << flag << endl;
        }
    
        return 0;
    }
    Naive Solution

    正确解法如下:

    对于已知的B 位理发师,我们可以知道,在第 t 时间单位的时候,可以有 number 个数的人已经理发

    因为我们要求的是第 n 个人是哪个理发师给他理发,那么从这里开始想下去

    可以考虑对时间进行二分

    找到第 t 时间单位,在那个时间点保证第 n 个人理发完毕

    好,那么我们有个这个时间 t 

    接下来就是找,是第几个理发师理的头发

    这时候需要一个新的变量 tt = t - 1, 表示在前一秒,我们可以在这里进行模拟

    如果 tt % a[i] == 0, 意思就是如果在 tt 的时间单位时第 i 个理发师可以理发,那么作累加

    直到刚刚好某个理发师碰到 第 n 个人的时候 break 输出答案即可。

    Source Code:

    //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
    #include <stdio.h>
    #include <iostream>
    #include <fstream>
    #include <cstring>
    #include <cmath>
    #include <stack>
    #include <string>
    #include <map>
    #include <set>
    #include <list>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #define Max(a,b) (((a) > (b)) ? (a) : (b))
    #define Min(a,b) (((a) < (b)) ? (a) : (b))
    #define Abs(x) (((x) > 0) ? (x) : (-(x)))
    #define MOD 1000000007
    #define pi acos(-1.0)
    
    using namespace std;
    
    typedef long long           ll      ;
    typedef unsigned long long  ull     ;
    typedef unsigned int        uint    ;
    typedef unsigned char       uchar   ;
    
    template<class T> inline void checkmin(T &a,T b){if(a>b) a=b;}
    template<class T> inline void checkmax(T &a,T b){if(a<b) a=b;}
    
    const double eps = 1e-7      ;
    const int M = 660000         ;
    const ll P = 10000000097ll   ;
    const int INF = 0x3f3f3f3f   ;
    const int MAX_N = 20         ;
    const int MAXSIZE = 101000000;
    
    const int MK = 100005;
    
    const int N = 1005;
    
    int b;
    
    ll n, a[N];
    
    ll cal(ll n) {                          //求出[0,n - 1] 时间内所有理发师理发的总人数
        ll ret = 0;
        for (int i = 0; i < b; ++i) {
            ret += (n - 1 + a[i]) / a[i];   //n - 1 表示(n - 1) 的时间, 表达式表示第i个理发师在前(n-1)时间内理发的人数
        }
        return ret;
    }
    
    int main() {
        ofstream fout ("B-large-practice.out");
        ifstream fin ("B-large-practice.in");
    
        int T, i, j, k;
        fin >> T;
        while (T--) {
            fin >> b >> n;
            for (i = 0; i < b; ++i) {
                fin >> a[i];
            }
            ll l = 0, r = n * MK;
            while (l < r) {
                ll mid = l + r >> 1;
                if (cal(mid) < n) {
                    l = mid + 1;
                } else {
                    r = mid;
                }
            }
            int last = cal(l - 1), ans = 0;
            for (i = 0; i < b; ++i) {
                if ((l - 1) % a[i] == 0) {
                    ++last;
                    if (last == n) {
                        ans = i + 1;
                        break;
                    }
                }
            }
            static int numCase = 0;
            fout << "Case #" << ++numCase << ": " << ans << endl;
        }
        return 0;
    }
  • 相关阅读:
    python 利用正则表达的式提取特定数据如手机号
    python 横向比较最大值 贴标签
    Go语言基础之17--Redis基本操作
    Mysql5.7.20源码编译安装
    Go语言基础之16--Mysql基本操作
    Go语言学习包(1)之bufio包
    Go语言基础之15--文件基本操作
    Go语言基础练习题系列5
    Go语言基础之14--Waitgroup和原子操作
    Go语言基础之13--线程安全及互斥锁和读写锁
  • 原文地址:https://www.cnblogs.com/wushuaiyi/p/4437464.html
Copyright © 2020-2023  润新知