4月10日 字节笔试题解
T1 简单模拟
思路一
我们只需考虑每块陆地周围的海洋个数。
思路二
如果陆地变成海洋之后可以再次影响陆地,那么这就是一道 BFS 标准题。给出AC代码:
#include <bits/stdc++.h> using namespace std; int m, n; #define getx(x) (x / n) #define gety(x) (x % n) #define inBound(x, y) (x >= 0 && x < m && y >= 0 && y < n) void solve() { cin >> m >> n; vector<string> g(m); for (int i = 0; i < m; ++i) { cin >> g[i]; } queue<int> q; vector<vector<bool>> vis(m, vector<bool>(n)); vector<vector<int>> power(m, vector<int>(n)); for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) { if (g[i][j] == '0') { q.push(i*n+j); vis[i][j] = 1; } } int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1}; while (!q.empty()) { auto f = q.front(); q.pop(); auto x = getx(f), y = gety(f); // cout << "front = " << x << ", " << y << endl; for (int k = 0; k < 4; ++k) { int nx = x + dx[k], ny = y + dy[k]; int no = nx * n + ny; if (inBound(nx, ny) && g[nx][ny] == '1' && power[nx][ny] < 2) { power[nx][ny]++; if (power[nx][ny] >= 2) { g[nx][ny] = '0'; } } } } for (int i = 0; i < m; ++i) cout << g[i] << endl; } int main() { int T = 0; cin >> T; while (T--) { solve(); } return 0; }
T2 贪心机器人
我们只需要维护一个机器人可以达到的最远距离即可。
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; vector<int> energy(n); for (int i = 0; i < n; ++i) { cin >> energy[i]; } int farthest = 0; for (int i = 0; i < n; ++i) { if (farthest < i) break; int nxt = i + energy[i]; if (nxt > farthest) farthest = nxt; } if (farthest >= n-1) cout << "TRUE" << endl; else cout << "FALSE" << endl; return 0; }
T4 凑成卡组的最少购买次数
这道题需要一些必备知识:位运算操作集合,状态压缩dp,子集枚举
思路
由于我们最后只需要凑成一套卡组(0~9 十种卡),因此我们考虑在选择第 个商品时,已经有的卡组为
,考虑第
个商品可以贡献的卡为
(
,
均为集合),最后的卡组集合将会是:
这样,我们在考虑选择第 个商品时,枚举集合
, 并记录当前状态下的最少要选
个商品。怎么更新
呢?
由于我们选择了第 个商品,并且其能贡献的卡组为
, 因此我们可以在
中减去
的所有子集(包括自己),这些状态集合为
、
...,
,那么转移方程将会是:
有了转移方程就可以轻松写出代码啦(已AC),下面给出代码:
#include <bits/stdc++.h> using namespace std; #define all (1 << 10) #define INF 0x3f3f3f3f vector<string> cards; int solve() { int m = cards.size(); vector<int> f(all, INF), g(all, INF); g[0] = 0; for (int i = 1; i <= m; ++i) { auto& card = cards[i-1]; int code = 0; for (auto c : card) { int idx = c - '0'; code |= (1 << idx); } for (int j = 0; j < all; ++j) { f[j] = g[j]; if ((j & code) != code) continue; // j 可以由 j ^ sub 转移得到 int sub = code; while (sub) { f[j] = min(f[j], g[j^sub]+1); sub = (sub-1)&code; } } swap(f, g); } if (g[all-1] >= INF) return -1; else return g[all-1]; } int main() { string s; while (cin >> s) { cards.push_back(s); } cout << solve() << endl; return 0; }#字节跳动##春招##实习##笔试题目##面经##C/C++#