日常刷题2025-2-17

日常刷题2025-2-17

建筑入门

rating:68 / 1279

https://ac.nowcoder.com/acm/contest/101921/E

思路:完全背包+构造

https://www.bilibili.com/video/BV1utKKe6EY9?spm_id_from=333.788.videopod.episodes&vd_source=4a339d299e165d8fe38b9926c5240eae&p=5

评述

题目的思维转换非常巧妙,完全想不到会是一道完全背包。

代码

#include <bits/stdc++.h>

using u64 = unsigned long long;
using i64 = long long;
typedef std::pair<int, int> pii;
const int mod = 998244353;
const long long LINF = 1e18;

void solve(){
    int n, k;
    std::cin >> n >> k;

    for (int i = 1; i <= n; i++){
        k -= i * i;
    }
    if (k < 0) {
        std::cout << "-1\n";
        return;
    }

    std::vector<int> a(n+2);
    for (int i = n; i >= 1; i--){
        a[i] = a[i+1] + i;
    }

    std::vector<int> dp(k+1);
    std::vector<pii> path(k+1);

    dp[0] = 1;
    for (int i = 1; i <= n; i++){
        for (int j = a[i]; j <= k; j++){
            if (dp[j-a[i]] && !dp[j]){
                dp[j] = 1;
                path[j] = {j - a[i], i};
            }
        }
    }

    if (!dp[k]){
        std::cout << "-1\n";
        return;
    }

    std::vector<int> nums;
    int cur = k;
    while (cur > 0){
        auto [pre, x] = path[cur];
        nums.emplace_back(x);
        cur = pre;
    }

    std::vector<int> ans(n+1);
    for (auto idx : nums){
        ans[idx]++;
    }

    for (int i = 1; i <= n; i++){
        ans[i] += ans[i-1];
    }

    for (int i = 1; i <= n; i++){
        ans[i] += i;
        std::cout << ans[i] << ' ';
    }
    std::cout << '\n';
}

signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(15);

    int t = 1, i;
    for (i = 0; i < t; i++){
        solve();
    }

    return 0;
}

猪猪养成计划2

rating:271 / 696

https://ac.nowcoder.com/acm/contest/99785/D

思路:分组背包

基本上一眼DP题,不过状态定义有点麻烦,一般来说,简单的DP定义都是题目问什么就定义什么,但是这题不同。如果思考每只猪是选择陪伴还是花钱的话,状态定义不下去。我们想看到的选与不选没有出现,有一个思维转换是我们最坏的情况下是每只猪都花钱,那么我们能得到一个花钱的最大值,在这个基础上在考虑哪只猪陪伴,这样题目就转换成了我们希望看到的选与不选了。

代码

#include <bits/stdc++.h>

using i64 = long long;
using u64 = unsigned long long;

typedef std::pair<long long, long long> PII;
const int mod = 998244353;
const int N = 2e6 + 1000;
const int INF = 0x3f3f3f3f;
const long long LINF = 1e18;
const double eps = 1e-12;
const double pi = std::acos(-1);
std::mt19937_64 rnd(std::chrono::steady_clock::now().time_since_epoch().count());
std::uniform_int_distribution<u64> dist_rand(mod / 2, mod - 1);

void solve() {
    int n, m;
    std::cin >> n >> m;
    std::vector<std::array<i64, 3>> a(n + 1);
    std::vector<std::vector<PII>> pos(n + 2);
    i64 res = 0;
    for (int i = 1; i <= n; i ++) std::cin >> a[i][0];
    for (int i = 1; i <= n; i ++) std::cin >> a[i][1] >> a[i][2], res += a[i][2];
    for (int i = 1; i <= n; i ++) pos[a[i][0]].emplace_back(a[i][1], a[i][2]);

    std::vector<i64> dp(n + 2, LINF);
    dp[0] = 0;
    for (int i = 0; i <= n; i ++) {
        for (auto [b, val] : pos[i]) dp[i + m] = std::min(dp[i + m], dp[i] - val + b);
        dp[i + 1] = std::min(dp[i + 1], dp[i]);
    }

    std::cout << res + dp[n + 1] << "\n";
}

signed main() {
    std::ios::sync_with_stdio(false), std::cin.tie(nullptr), std::cout.tie(nullptr);
    
    int tmp = 1;
    
    // std::cin >> tmp;

    while (tmp--)
        solve();

    return 0;
}

posted @ 2025-02-17 11:51  califeee  阅读(10)  评论(0)    收藏  举报