• Google KickStart 2020 RoundA


    第一题:Allocation

    题意:N个房子,第i个房子价格为Ai美元,用B美元最多买几个房子。

    Limit:

    1 ≤ T ≤ 100.
    1 ≤ B ≤ 10^5.
    1 ≤ Ai ≤ 1000, for all i.
    1 ≤ N ≤ 10^5.

    分析:按价格从小到大排序即可。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<iostream>
    #include<set>
    #include<map>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<sstream>
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    const int MAXN = 100000 + 10;
    const double eps = 1e-8;
    int dcmp(double a, double b){
        if(fabs(a - b) < eps) return 0;
        return a < b ? -1 : 1;
    }
    int a[MAXN];
    int main(){
        int T;
        scanf("%d", &T);
        for(int Case = 1; Case <= T; ++Case){
            int N, B;
            scanf("%d%d", &N, &B);
            for(int i = 0; i < N; ++i){
                scanf("%d", &a[i]);
            }
            sort(a, a + N);
            int sum = 0;
            int cnt = 0;
            for(int i = 0; i < N; ++i){
                if(sum + a[i] <= B){
                    sum += a[i];
                    ++cnt;
                }
                else break;
            }
            printf("Case #%d: %d
    ", Case, cnt);
        }
        return 0;
    }
    

    第二题:Plates

    题意:有N堆盘子,每堆k个盘子,每个盘子有个beauty value。当拿某个盘子时,该盘子之上的盘子也会被拿起。问当拿P个盘子时,能获得最大的beauty value值。

    Limit:

    1 ≤ T ≤ 100.
    1 ≤ K ≤ 30.
    1 ≤ P ≤ N * K.
    The beauty values are between 1 and 100, inclusive.
    1 ≤ N ≤ 50.
    

    分析:dp[i][j]表示前i堆拿j个盘子能获得的最大beauty value值。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<iostream>
    #include<set>
    #include<map>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<sstream>
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    const int MAXN = 100000 + 10;
    const double eps = 1e-8;
    int dcmp(double a, double b){
        if(fabs(a - b) < eps) return 0;
        return a < b ? -1 : 1;
    }
    int a[55][35];
    int dp[55][1510];   //dp数组第二维比赛时开小了
    int sum[55][35];
    int main(){
        int T;
        scanf("%d", &T);
        for(int Case = 1; Case <= T; ++Case){
            int N, K, P;
            scanf("%d%d%d", &N, &K, &P);
            memset(sum, 0, sizeof sum);
            for(int i = 1; i <= N; ++i){
                for(int j = 1; j <= K; ++j){
                    scanf("%d", &a[i][j]);
                    sum[i][j] = sum[i][j - 1] + a[i][j];
                }
            }
            memset(dp, 0, sizeof dp);
            for(int i = 1; i <= N; ++i){
                for(int j = 0; j <= P; ++j){
                    dp[i][j] = max(dp[i][j], dp[i - 1][j]);
                    for(int k = 1; k <= K && k <= j; ++k){
                        dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + sum[i][k]);
                    }
                }
            }
            printf("Case #%d: %d
    ", Case, dp[N][P]);
        }
        return 0;
    }
    

    优化一下,只开一维dp数组~

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<iostream>
    #include<set>
    #include<map>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<sstream>
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    const int MAXN = 100000 + 10;
    const double eps = 1e-8;
    int dcmp(double a, double b){
        if(fabs(a - b) < eps) return 0;
        return a < b ? -1 : 1;
    }
    int a[55][35];
    int dp[1510];
    int sum[55][35];
    int main(){
        int T;
        scanf("%d", &T);
        for(int Case = 1; Case <= T; ++Case){
            int N, K, P;
            scanf("%d%d%d", &N, &K, &P);
            memset(sum, 0, sizeof sum);
            for(int i = 1; i <= N; ++i){
                for(int j = 1; j <= K; ++j){
                    scanf("%d", &a[i][j]);
                    sum[i][j] = sum[i][j - 1] + a[i][j];
                }
            }
            memset(dp, 0, sizeof dp);
            for(int i = 1; i <= N; ++i){
                for(int j = P; j >= 0; --j){
                    for(int k = 1; k <= K && k <= j; ++k){
                        dp[j] = max(dp[j], dp[j - k] + sum[i][k]);
                    }
                }
            }
            printf("Case #%d: %d
    ", Case, dp[P]);
        }
        return 0;
    }
    

    第三题:Workout

    题意:有N个session,每个session长达Mi分钟。定义diff为相邻session差值的最大值,要求增加至多K个session,使得diff最小,求最小的diff。(N个session的时长是严格递增的,要求增加k个session后,所有session时长也是严格递增的)

    Limit:

    1 ≤ T ≤ 100.
    For at most 10 test cases, 2 ≤ N ≤ 10^5.
    For all other test cases, 2 ≤ N ≤ 300.
    1 ≤ Mi ≤ 10^9.
    Mi < Mi+1 for all i.
    1 ≤ K ≤ 10^5.
    

    分析:二分diff求右临界值即可。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<iostream>
    #include<set>
    #include<map>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<sstream>
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    const int MAXN = 100000 + 10;
    const double eps = 1e-8;
    int dcmp(double a, double b){
        if(fabs(a - b) < eps) return 0;
        return a < b ? -1 : 1;
    }
    int a[MAXN];
    int N, K;
    bool judge(int x){
        int cnt = 0;
        for(int i = 2; i <= N; ++i){
            if(a[i] - a[i - 1] > x){
                int tmp = a[i - 1];
                while(tmp + x < a[i]){
                    ++cnt;
                    if(cnt > K) return false;
                    tmp += x;
                }
            }
        }
        return true;
    }
    int main(){
        int T;
        scanf("%d", &T);
        for(int Case = 1; Case <= T; ++Case){
            scanf("%d%d", &N, &K);
            int diff = 0;
            for(int i = 1; i <= N; ++i){
                scanf("%d", &a[i]);
                if(i > 1){
                    diff = max(diff, a[i] - a[i - 1]);
                }
            }
            int l = 1;
            int r = diff;
            while(l < r){
                int mid = l + (r - l) / 2;
                if(judge(mid)) r = mid;
                else l = mid + 1;
            }
            printf("Case #%d: %d
    ", Case, r);
        }
        return 0;
    }
    

    第四题:Bundling

    题意:有N个字符串,每个字符串只包含字母A~Z,要求把字符串按K个一组进行分组,每个字符串只能分到一个组中。分好后,每个组的score为该组所有字符串的最长公共前缀。问分组后每个组的score之和的最大值。

    Limit:

    1 ≤ T ≤ 100.
    2 ≤ N ≤ 105.
    2 ≤ K ≤ N.
    K divides N.
    Each of Pip's strings contain at least one character.
    Each string consists only of letters from A to Z.
    The total number of characters in Pip's strings across all test cases is at most 2 × 106.
    

    分析:

    (1)对于N个字符串中所有可能的前缀来说,假如某个前缀p存在于cnt个字符串中,则它对最终答案的贡献是cnt/K。累加所有的前缀贡献即可。

    (2)计算每个前缀存在于多少个字符串中,用Trie树即可。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<iostream>
    #include<set>
    #include<map>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<sstream>
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    const int MAXN = 100000 + 10;
    const double eps = 1e-8;
    int dcmp(double a, double b){
        if(fabs(a - b) < eps) return 0;
        return a < b ? -1 : 1;
    }
    struct TreeNode{
        int val;
        TreeNode *nex[26];
        TreeNode(){
            val = 0;
            for(int i = 0; i < 26; ++i) nex[i] = NULL;
        }
    };
    string s[MAXN];
    void build(string x, TreeNode* root){
        int len = x.size();
        for(int i = 0; i < len; ++i){
            int cur = x[i] - 'A';
            if(root -> nex[cur] == NULL){
                root -> nex[cur] = new TreeNode();
            }
            root = root -> nex[cur];
            ++root -> val;
        }
    }
    int bfs(TreeNode* root, int K){
        int ans = 0;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty()){
            TreeNode *cur = q.front();
            q.pop();
            ans += cur -> val / K;
            for(int i = 0; i < 26; ++i){
                if(cur -> nex[i] != NULL){
                    q.push(cur -> nex[i]);
                }
            }
        }
        return ans;
    }
    int main(){
        int T;
        scanf("%d", &T);
        for(int Case = 1; Case <= T; ++Case){
            int N, K;
            scanf("%d%d", &N, &K);
            TreeNode *root = new TreeNode();
            for(int i = 0; i < N; ++i){
                cin >> s[i];
                build(s[i], root);
            }
            printf("Case #%d: %d
    ", Case, bfs(root, K));
        }
        return 0;
    }
    

    也可以省掉bfs~

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<iostream>
    #include<set>
    #include<map>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<sstream>
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    const int MAXN = 100000 + 10;
    const double eps = 1e-8;
    int dcmp(double a, double b){
        if(fabs(a - b) < eps) return 0;
        return a < b ? -1 : 1;
    }
    struct TreeNode{
        int val;
        TreeNode *nex[26];
        TreeNode(){
            val = 0;
            for(int i = 0; i < 26; ++i) nex[i] = NULL;
        }
    };
    string s[MAXN];
    void build(string x, TreeNode* root, int K, int &ans){
        int len = x.size();
        for(int i = 0; i < len; ++i){
            int cur = x[i] - 'A';
            if(root -> nex[cur] == NULL){
                root -> nex[cur] = new TreeNode();
            }
            root = root -> nex[cur];
            ++root -> val;
            if(root -> val == K){
                ++ans;
                root -> val = 0;
            }
        }
    }
    int main(){
        int T;
        scanf("%d", &T);
        for(int Case = 1; Case <= T; ++Case){
            int N, K;
            scanf("%d%d", &N, &K);
            TreeNode *root = new TreeNode();
            int ans = 0;
            for(int i = 0; i < N; ++i){
                cin >> s[i];
                build(s[i], root, K, ans);
            }
            printf("Case #%d: %d
    ", Case, ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    char array 与string
    汗= =
    看来要学 Asp.Net 了
    安装 Xamarin for Visual Studio
    Xamarin for Visual Studio 3.11.658 Alpha 版 破解补丁
    用 Xamarin for VS 创建 aar 文件的绑定
    Android中当前墙纸Wallpaper存放的位置
    Android中动态改变控件的大小的一种方法
    程序员学习能力提升三要素(读书笔记)
    让Android软键盘默认进入英文键盘
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/12546794.html
Copyright © 2020-2023  润新知