牛客周賽 Round 40

PHarr發表於2024-05-06

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;
}

相關文章