Google kickstart 2020 Round A题解

A题题意:给定n个房子及其价格,自己有B美元,求最多能买多少个房子

题解:将房子价钱排序后从小到大购买即可。

AC代码:

#include
using namespace std;
int main() {
    int t;
    int n;
    int budgt;
    cin>>t;
    for (int j = 1; j <= t; j++) {
        cin>>n;
        cin>>budgt;
        vector dp;
        for (int i = 1; i <= n; i++) {
            int x;
            cin>>x;
            dp.push_back(x);
        }
        sort(dp.begin(), dp.end());
        int ans = 0;
        for (int i = 0; i < dp.size(); i++) {
            if (budgt >= dp[i]) {
                budgt -= dp[i];
                ans++;
            }
        }
        printf("Case #%d: %d\n", j,ans);
    }
    return 0;
}

B题题意:桌子上有N堆盘子,每堆有K个盘子,每个盘子有一个观赏值,对于每一堆盘子,每次只能从上打下拿盘子,求最多拿取P个盘子能获得的总价值。

题解:动态规划,sum[i][j]为价值前缀和,即sum[i][j]表示对于第i堆盘子,拿取前j个盘子获得的总价值。dp[i][j]表示前i堆盘子中拿取j个盘子能获得的最大值。转移方程dp[i][j] = max(dp[i][j], dp[i - 1][j - l] + sum[i][l]),其中0 < i <= n,0 <= j <= p。

AC代码:

#include
using namespace std;
int sum[55][33];
int dp[55][1507];
int a[55][33];
int main() {
    int t;
    int n;
    int k;
    int p;
    cin>>t;
    for (int j = 1; j <= t; j++) {
        cin>>n>>k>>p;
        memset(dp, 0, sizeof(dp));
        memset(sum, 0, sizeof(sum));
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= k; j++) cin>>a[i][j];
        }
        for (int i = 1; i <= n; i++) {
            sum[i][1] = a[i][1];
            for (int j = 2; j <= k; j++) sum[i][j] = sum[i][j - 1] + a[i][j];
        }
        int ans = 0;
        for (int i = 1; i <= k; i++) dp[1][i] = sum[1][i];
        for (int i = 2; i <= n; i++) {
            for (int j = 0; j <= p; j++) {
                if (j > i * k) break;
                for (int l = 0; l <= k; l++) {
                    if (j >= l) dp[i][j] = max(dp[i][j], dp[i - 1][j - l] + sum[i][l]);
                }
            }
        }
        ans = dp[n][p];
        printf("Case #%d: %d\n", j,ans);
    }
    return 0;
}

C题题意:给定n个递增的数,然后向数组中插入k个数使得数组仍然递增,求插入后两个相邻元素差值的最小值是多少。

题解:二分最小差值,然后判断当前差值是否都达到即可。

AC代码:

#include
using namespace std;
const int maxn = 1e5 + 7;
int a[maxn];
int n;
int k;
bool check(int mid) {
    int now = 0;
    int last = a[1];
    int p = 2;
    while (p <= n) {
        if (a[p] - last > mid) {
            now++;
            last = last + mid;
        } else {
            last = a[p];
            p++;
        }
    }
    return now <= k;
}
int main() {
    int t;

    cin>>t;
    for (int j = 1; j <= t; j++) {
        cin>>n>>k;
        for (int i = 1; i <= n; i++) cin>>a[i];
        int l = 1;
        int r = 0;
        int ans = 1;
        for (int i = 2; i <= n; i++) r = max(a[i] - a[i - 1], r);
        while (l <= r) {
            int mid = (l + r) / 2;
            if (check(mid)) {
                r = mid - 1;
                ans = mid;
            }
            else l = mid + 1;
        }
        printf("Case #%d: %d\n", j, ans);
    }
    return 0;
}

D题题意:给定N个只包含大写字母的字符串,将其分为P组,每组有K个字符串,P*K = N,每组的价值为最长公共前缀的长度,求所有组的最大总价值和。

题解:先将字符串按字典序排序后,dfs(i, j, k)表示第i个字符串到第j个字符串的第k位。如果i -> j中的第k位相同的字符串数大于K,说明当前字符串分为一组后能使得总价值+1,将第k位都相同的字符串截止dfs即可。

AC代码:

#include
using namespace std;
const int maxn = 1e5 + 7;
vector a;
int ans;
int n, k;
void dfs(int l, int r, int w) {
    int last = l;
    int sum = 1;
    for (int i = l; i <= r; i++) {
        if (i < r && i < n - 1 && a[i].length() > w && a[i + 1].length() > w && a[i][w] == a[i + 1][w]) {
            sum++;
            continue;
        }
        if (sum >= k) {
            ans += sum / k;
            dfs(last, i, w + 1);
        }
        last = i + 1;
        sum = 1;
    }
}
int main() {
    int t;
    scanf("%d", &t);
    for (int j = 1; j <= t; j++) {
        scanf("%d%d", &n, &k);
        a.clear();
        ans = 0;
        for (int i = 1; i<= n; i++){
            char pp[maxn* 20];
            scanf("%s", &pp);
            a.push_back(pp);
        }
        sort(a.begin(), a.end());
        if (k == 1) {
            for (int i = 0; i < n; i++) ans += a[i].length();
            printf("Case #%d: %d\n", j,ans);
            continue;
        }
        int l = 0;
        int sum = 1;
        for (int i = 0; i < n; i++) {
            if (i < n - 1 && a[i][0] == a[i + 1][0]) {
                sum++;
                continue;
            }
            if (sum >= k) {
                ans += sum / k;
                dfs(l, i, 1);
            }
            l = i + 1;
            sum = 1;
        }
        printf("Case #%d: %d\n", j,ans);
    }
    return 0;
}

 

你可能感兴趣的:(kickstart)