牛客周赛 Round 40
A-小红进地下城
a = input()
b = input()
if a == b :
print("Yes")
else:
print("No")
B-小红打怪
#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;
}
C-小红的排列构造
每种数字出现的次数不能超过两次
#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;
}
D-小红升装备
首先最简单想法肯定是枚举一下这个武器生了多少级,然后进行转移
#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(nx^2)\)
但实际上,购买物品可以当作是01背包、升级的部分可以当作多重背包,但是多重背包必须有01背包的依赖。所以我们可以先01背包,且强制选择,然后用二进制优化多重背包部分。复杂度是\(O(nx\log lvmax)\)
#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;
}
E-小红的矩阵划分
有一个小结论是,如果\(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;
}