kickstart 2021 round A

Posted clara-pointer-zhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kickstart 2021 round A相关的知识,希望对你有一定的参考价值。

刚开始刷,记录一下,都是在练习模式下做的

K-Goodness String

 

 代码:

#include <iostream>
#include <string>
using namespace std;
int main(){
    int t;
    cin >> t;
    for(int j = 1; j <= t; ++j){
        int n, k;
        cin >> n >> k;
        string s;
        cin >> s;
        int score = 0;
        for(int i = 1; i <= n / 2; ++i){
            if(s[i - 1] != s[n - i]) score++;
        }
        cout << "Case #" << j << ": " << abs(k - score) << endl;
    }
    return 0;
}

L Shaped Plots

 

思路:

考虑将每一个点作为L形状的端点,在8种情况中取四种情况避免重复计算,想来想去把自己绕晕了,参考题解将每一个点作为拐点瞬间清晰了许多

代码:

#include<iostream>
#include<vector>
using namespace std;
int cal(int se, int le1, int le2) {
    int res = 0;
    int maxi = le1 > le2 ? le1 : le2;
    for (int i = 2; i <= se && i + i <= maxi; ++i) {
        res += (i + i <= le1);
        res += (i + i <= le2);
    }
    return res;
}
int main() {
    int t;
    cin >> t;
    for (int caseid = 1; caseid <= t; caseid++) {
        int r, c;
        cin >> r >> c;
        vector<vector<int>> grid(r, vector<int>(c, 0));
        for (int i = 0; i < r; ++i) {
            for (int j = 0; j < c; ++j) cin >> grid[i][j];
        }
        int res = 0;
        for (int i = 0; i < r; ++i) {
            for (int j = 0; j < c; ++j) {
                if (!grid[i][j]) continue;
                int up = 1, down = 1, left = 1, right = 1;
                for (int k = i - 1; k >= 0; --k) {
                    if (grid[k][j]) up++;
                    else break;
                }
                for (int k = i + 1; k < r; ++k) {
                    if (grid[k][j]) down++;
                    else break;
                }
                for (int k = j - 1; k >= 0; --k) {
                    if (grid[i][k]) left++;
                    else break;
                }
                for (int k = j + 1; k < c; ++k) {
                    if (grid[i][k]) right++;
                    else break;
                }
                if (up > 1) res += cal(up, left, right);
                if (down > 1) res += cal(down, left, right);
                if (left > 1) res += cal(left, up, down);
                if (right > 1) res += cal(right, up, down);
            }
        }
        cout << "Case #" << caseid << ": " << res << endl;
    }
}

Rabbit House

 

 思路:

首先很自然想到使用优先队列,从高度最大的cell开始更新它四周的cell,但在如何更新上犯了难,参考题解,直接插入配合状态数组

代码:

#include<iostream>
#include<queue>
using namespace std;
int main() {
    int t;
    cin >> t;
    vector<vector<int>> dir = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
    for (int caseid = 1; caseid <= t; ++caseid) {
        int r, c;
        cin >> r >> c;
        long long res = 0;
        
        priority_queue<pair<long long, pair<int, int>>> pq;
        vector<vector<long long>> grid(r, vector<long long>(c, 0));
        for (int i = 0; i < r; ++i) {
            for (int j = 0; j < c; ++j) {
                cin >> grid[i][j];
                pq.push({ grid[i][j], {i, j} });
            }
        }
        vector<vector<bool>> st(r, vector<bool>(c, false));
        while (pq.size()) {
            auto i = pq.top();
            pq.pop();
            long long h = i.first;
            auto j = i.second;
            int x = j.first, y = j.second;
            if (st[x][y]) continue;
            st[x][y] = true;
            for (auto d : dir) {
                int dx = x + d[0];
                if (dx < 0 || dx >= r) continue;
                int dy = y + d[1];
                if (dy < 0 || dy >= c) continue;
                if(st[dx][dy]) continue;
                if (grid[dx][dy] < h - 1) {
                    res += h - 1 - grid[dx][dy];
                    grid[dx][dy] = h - 1;
                    pq.push({ h - 1, {dx, dy} });
                }
            }
        }
        cout << "Case #" << caseid << ": ";
        cout << res << endl;
    }
}

Checksum

 

思路:

看了半天题解才懂,直接复制过来,对于任何一行或一列,如果我们只有一个值是未知的,我们可以用所有其他值异或上异或和便可以求解这个值;如果有至少两个位置未知,那么我们便无法求解。考虑每一个A[i][j] = -1的位置,我们每一行和每一列最多有1个值是可以通过当列(行)的异或值自己求出来的,那么我们应该尽量选取B[i][j]更大的值来节省时间。怎样找到这样的点的集合呢?由于每列(行)最多使用一次,我们可以把每一行(列)看成一个点,可以把每个A[i][j]看成是把第i行和第j列连接起来的边,在生成图中找最大生成树,组成最大生成树的边集就是我们要找的点集。答案为所有A[i][j]=-1的B[i][j]之和减去最大生成树的边权和。

代码:

#include<iostream>
#include<vector>
using namespace std;
const int N = 1010;
int p[N];
int find(int x){
    if(x != p[x]) p[x] = find(p[x]);
    return p[x];
}
int main(){
    int T;
    cin >> T;
    for(int t = 1; t <= T; ++t){
        int n;
        cin >> n;
        vector<vector<int>> a(n, vector<int>(n, 0));
        vector<vector<int>> b(n, vector<int>(n, 0));
        vector<int> r(n, 0);
        vector<int> c(n, 0);
        for(int i = 0; i < n; ++i){
            for(int j = 0; j < n; ++j) cin >> a[i][j];
        }
        for(int i = 0; i < n; ++i){
            for(int j = 0; j < n; ++j) cin >> b[i][j];
        }
        for(int i = 0; i < n; ++i) cin >> r[i];
        for(int i = 0; i < n; ++i) cin >> c[i];
        vector<vector<int>> vec(1001);
        int sumcost = 0;
        for(int i = 0; i < n; ++i){
            for(int j = 0; j < n; ++j){
                if(a[i][j] == -1){
                    sumcost += b[i][j];
                    vec[b[i][j]].push_back(i);
                    vec[b[i][j]].push_back(j + n);
                }
            }
        }
        for(int i = 0; i < n + n; ++i) p[i] = i;
        for(int val = 1000; val >= 0; --val){
            auto v = vec[val];
            for(int i = 0; i < v.size(); i += 2){
                int x = find(v[i]), y = find(v[i + 1]);
                if(x != y){
                    sumcost -= val;
                    p[x] = y;
                }
            }
        }
        cout << "Case #" << t << ": " << sumcost << endl;
    }
}

 

以上是关于kickstart 2021 round A的主要内容,如果未能解决你的问题,请参考以下文章

Google Kickstart 2020 Round A 分配问题

Deltix Round, Summer 2021 (open for everyone, rated, Div. 1 + Div. 2) D. Take a Guess (交互,位运算性质)(代码片

2019 google kickstart round A

Google Kickstart 2020 Round A: Plates Solution

2019 Google Kickstart Round H

Kickstart2018 Round (Practice ~ H)