牛客周赛 Round 40

1|0A-小红进地下城


a = input() b = input() if a == b : print("Yes") else: print("No")

2|0B-小红打怪


#include <bits/stdc++.h> using namespace std; int main() { int n, m; cin >> n >> m; vector<string> s(n); for (auto &i: s) cin >> i; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) { if (s[i][j] == '.' or s[i][j] == '*') continue; int res = 0; if (s[i][j] == 'W') { for (int x = i, y = j; x >= 0; x--) res += s[x][y] == '*'; } else if (s[i][j] == 'S') { for (int x = i, y = j; x < n; x++) res += s[x][y] == '*'; } else if (s[i][j] == 'A') { for (int x = i, y = j; y >= 0; y--) res += s[x][y] == '*'; } else { for (int x = i, y = j; y < m; y++) res += s[x][y] == '*'; } cout << res << "\n"; return 0; } return 0; }

3|0C-小红的排列构造


每种数字出现的次数不能超过两次

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = int64_t; using vi = vector<i64>; using pii = pair<i64, i64>; const i64 inf = 1e18; const i64 mod = 1e9 + 7; #define int i64 i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vi p(n), q(n), vp(n + 1), vq(n + 1); for (int i = 0, x; i < n; i++) { cin >> x; if (vp[x] == 0) { vp[x] = 1, p[i] = x; } else if (vq[x] == 0) { vq[x] = 1, q[i] = x; } else { cout << "-1\n"; return 0; } } for (int i = 0, j = 1; i < n; i++) { while (vp[j] == 1) j++; if (p[i] == 0) p[i] = j, vp[j] = 1; } for (int i = 0, j = 1; i < n; i++) { while (vq[j] == 1) j++; if (q[i] == 0) q[i] = j, vq[j] = 1; } for (auto i: p) cout << i << " "; cout << "\n"; for (auto i: q) cout << i << " "; cout << "\n"; return 0; }

4|0D-小红升装备


首先最简单想法肯定是枚举一下这个武器生了多少级,然后进行转移

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = int64_t; using vi = vector<i64>; using pii = pair<i64, i64>; const i64 inf = 1e18; const i64 mod = 1e9 + 7; #define int i64 i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m; cin >> n >> m; vi f(m + 1); for (int i = 1, att, price, cost, upgrade, lv; i <= n; i++) { cin >> att >> price >> cost >> upgrade >> lv; vi g = f; for (int j = lv, v = price + lv * cost, w = att + lv * upgrade; j >= 0; j--, v -= cost, w -= upgrade) { for (int k = m; k >= v; k--) g[k] = max(g[k], f[k - v] + w); } f = move(g); } cout << *max_element(f.begin(), f.end()) << "\n"; return 0; }

这个做个会TLE,当实际上我们发现m的范围很小,所以我们可以限制一下枚举的范围。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = int64_t; using vi = vector<i64>; using pii = pair<i64, i64>; const i64 inf = 1e18; const i64 mod = 1e9 + 7; #define int i64 i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m; cin >> n >> m; vi f(m + 1); for (int i = 1, att, price, cost, upgrade, lv; i <= n; i++) { cin >> att >> price >> cost >> upgrade >> lv; if (price > m) continue; vi g = f; for (int j = min(lv, (m - price) / cost), v = price + j * cost, w = att + j * upgrade; j >= 0; j--, v -= cost, w -= upgrade) { for (int k = m; k >= v; k--) g[k] = max(g[k], f[k - v] + w); } f = move(g); } cout << *max_element(f.begin(), f.end()) << "\n"; return 0; }

这个做法是可以通过的,复杂度是O(nx2)

但实际上,购买物品可以当作是01背包、升级的部分可以当作多重背包,但是多重背包必须有01背包的依赖。所以我们可以先01背包,且强制选择,然后用二进制优化多重背包部分。复杂度是O(nxloglvmax)

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using vi = vector<i64>; using pii = pair<i64, i64>; const i64 inf = 1e18; const i64 mod = 1e9 + 7; #define int long long i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m; cin >> n >> m; vi f(m + 1); for (int i = 1, att, price, cost, upgrade, lv; i <= n; i++) { cin >> att >> price >> cost >> upgrade >> lv; vi g(m + 1); for (int j = m; j >= price; j--) g[j] = f[j - price] + att; vector<pii> a; for (int j = 1; lv > 0; j *= 2) { if (j <= lv) a.emplace_back(cost * j, upgrade * j), lv -= j; else a.emplace_back(cost * lv, upgrade * lv), lv = 0; } for (const auto &[v, w]: a) for (int j = m; j >= v + price; j--) g[j] = max(g[j], g[j - v] + w); for (int j = 0; j <= m; j++) f[j] = max(f[j], g[j]); } cout << *max_element(f.begin(), f.end()) << "\n"; return 0; }

5|0E-小红的矩阵划分


有一个小结论是,如果n是3 的倍数,则只用L或只用正方形都可以填满,反之用L的一定可以只剩一个空格子。

所以当n是 3 的倍数时,考虑两种方案哪一个填满更优。

否则用L形尽可能填满,将最后一个没填满和L替换为一个正方形,用正方形填满。三种方式取最优解即可。

#include <bits/stdc++.h> using namespace std; using i64 = long long; int main(){ i64 n, x, y; cin >> n >> x >> y; if(n % 3 == 0) cout << max(n * n / 3 * x, n * n / 4 * y); else cout << max({n * n / 3 * x, n * n / 3 * x - x + y, n * n / 4 * y}); return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/18175559.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2023-05-06 AtCoder Beginner Contest 242
2023-05-06 矩阵加速递推
点击右上角即可分享
微信分享提示