AtCoder Beginner Contest 404
A - Not Found
点击查看代码
void solve() {
std::string s;
std::cin >> s;
std::array<int, 26> cnt{};
for (auto & c : s) {
cnt[c - 'a'] = 1;
}
for (int i = 0; i < 26; ++ i) {
if (!cnt[i]) {
std::cout << (char)('a' + i) << "\n";
return;
}
}
}
B - Grid Rotation
题意:给你两个\(01\)矩阵\(a, b\),要使得\(a\)变成\(b\)。你每次可以更改\(a\)任意一个位置的值,或者将\(a\)顺时针旋转90度。求最小操作数。
最多旋转三次。那么枚举旋转次数,每个计算最小值。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<std::string> s(n), t(n);
for (int i = 0; i < n; ++ i) {
std::cin >> s[i];
}
for (int i = 0; i < n; ++ i) {
std::cin >> t[i];
}
auto get = [&]() -> int {
int res = 0;
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < n; ++ j) {
res += s[i][j] != t[i][j];
}
}
return res;
};
int ans = get();
for (int k = 1; k < 4; ++ k) {
auto ns = s;
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < n; ++ j) {
ns[j][n - 1 - i] = s[i][j];
}
}
s = ns;
ans = std::min(ans, get() + k);
}
std::cout << ans << "\n";
}
C - Cycle Graph?
题意:给你一个图,判断这个图是不是恰好有一个环。
要图联通且边数等于点数且每个点度数都是2才满足条件。
点击查看代码
struct DSU {
std::vector<int> fa, cnt;
DSU(int _n) {
init(_n);
}
void init(int _n) {
fa.assign(_n, 0);
cnt.assign(_n, 1);
std::iota(fa.begin(), fa.end(), 0);
}
int find(int x) {
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
bool merge(int x, int y) {
x = find(x), y = find(y);
if (x == y) {
return false;
}
fa[y] = x;
cnt[x] += cnt[y];
return true;
}
bool same(int x, int y) {
return find(x) == find(y);
}
int size(int x) {
return cnt[find(x)];
}
};
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<int> in(n);
DSU dsu(n);
for (int i = 0; i < m; ++ i) {
int u, v;
std::cin >> u >> v;
-- u, -- v;
++ in[u], ++ in[v];
dsu.merge(u, v);
}
int cnt = 0;
for (int i = 0; i < n; ++ i) {
cnt += dsu.find(i) == i;
}
if (n == m && std::ranges::count(in, 2) == n && cnt == 1) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
D - Goin' to the Zoo
题意:\(n\)个动物园,\(m\)种动物。每个动物园有一些动物,门票为\(c_i\)。求每个动物看两次以上的最少花费。
显然一个动物园最多看两次,那么每个动物园有3种选择,一共\(3^n\)种方案,暴力枚举计算花费即可。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<int> c(n);
for (int i = 0; i < n; ++ i) {
std::cin >> c[i];
}
std::vector<std::vector<int>> a(n);
for (int i = 0; i < m; ++ i) {
int k;
std::cin >> k;
while (k -- ) {
int x;
std::cin >> x;
-- x;
a[x].push_back(i);
}
}
i64 ans = 1e18;
int tot = std::pow(3, n);
for (int i = 0; i < tot; ++ i) {
i64 sum = 0;
std::vector<int> st(m);
for (int j = 0, p = 1; j < n; ++ j, p *= 3) {
int cnt = i % (p * 3) / p;
for (auto & x : a[j]) {
st[x] += cnt;
}
sum += cnt * c[j];
}
bool flag = true;
for (int i = 0; i < m; ++ i) {
flag &= st[i] >= 2;
}
if (flag) {
ans = std::min(ans, sum);
}
}
std::cout << ans << "\n";
}
E - Bowls and Beans
题意:有\(n\)个位置\([0, n - 1]\),每个位置可以把自己的豆子给\([i - c_i, i - 1]\)的位置。求最多给几次所有豆子都在\(0\)的位置。
从后往前做,每次应该优先给有豆子且\(i-c_i\)最小的位置。如果都没有豆子,则直接选择\(i-c_i\)最小的。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> c(n), a(n);
for (int i = 1; i < n; ++ i) {
std::cin >> c[i];
c[i] = i - c[i];
}
for (int i = 1; i < n; ++ i) {
std::cin >> a[i];
}
int ans = 0;
for (int i = n - 1; i > 0; -- i) {
if (!a[i]) {
continue;
}
++ ans;
int p = -1;
for (int j = c[i]; j < i; ++ j) {
if (a[j] && (p == -1 || c[j] < c[p])) {
p = j;
}
}
if (p == -1) {
for (int j = c[i]; j < i; ++ j) {
if (p == -1 || c[j] < c[p]) {
p = j;
}
}
}
a[p] += a[i];
}
std::cout << ans << "\n";
}
F - Lost and Pound
待补。
G - Specified Range Sums
题意:一个正整数数组\(a\),满足\(m\)个条件:\(\sum_{i=L_i}^{R_i} a_i = s_i\)。求\(a\)的最小和。
转化为前缀和运算。那么就是\(sum[R_i] - sum[L_i - 1] = s_i\)以及\(sum[i] - sum[i - 1] \geq 1\)。使得\(sum[n]\)最小。
那么可以差分约束。\(sum[R_i] - sum[L_i - 1] = s_i\)可以表示为\(sum[R_i] - sum[L_i - 1] \geq s_i\)以及\(sum[R_i] - sum[L_i - 1] \leq s_i\),那么可以从\(i-1\)向\(i\)连\(1\)的边,\(L_{i} - 1\)向\(R_i\)连\(s_i\)的边,\(R_i\)向\(L_i - 1\)连\(-s_i\)的边。直接跑最长路,如果有正权环则无解。
这题卡\(spfa\),需要用\(bellman\_ ford\)。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<std::vector<std::pair<int, int>>> adj(n + 1);
auto addEdge = [&](int u, int v, int w) -> void {
adj[u].emplace_back(v, w);
};
for (int i = 0; i < m; ++ i) {
int l, r, s;
std::cin >> l >> r >> s;
addEdge(l - 1, r, s);
addEdge(r, l - 1, -s);
}
for (int i = 1; i <= n; ++ i) {
addEdge(i - 1, i, 1);
}
const i64 inf = 1e18;
std::vector<i64> dist(n + 1, -inf);
dist[0] = 0;
for (int i = 0; i <= n + 1; ++ i) {
bool flag = false;
for (int u = 0; u <= n; ++ u) {
for (auto & [v, w] : adj[u]) {
if (dist[v] < dist[u] + w) {
dist[v] = dist[u] + w;
flag = true;
}
}
}
if (!flag) {
break;
} else {
if (i > n) {
std::cout << -1 << "\n";
return;
}
}
}
std::cout << dist[n] << "\n";
}

浙公网安备 33010602011771号