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 (交互,位运算性质)(代码片