1 条题解

  • 0
    @ 2025-5-24 9:33:31

    建图及调试(看看有没有建对)

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 200;
    int n;
    int val[MAXN + 5]; // 叶子结点的画的数量
    int tot;           // 开了多少个节点
    // <子节点 v, 边权 w>
    vector<pair<int, int>> e[MAXN + 5];
    // 返回当前建树后的根节点以及到根节点的边权
    pair<int, int> dfs()
    {
        int u, w, x;
        u = ++tot;
        cin >> w >> x;
        cout << w << " " << x << endl;
        if (x != 0)
            val[u] = x;
        else
        {
            e[u].push_back(dfs());
            e[u].push_back(dfs());
        }
        return {u, w};
    }
    void dfsShow(int u)
    {
        for (int i = 0; i < e[u].size(); i++)
        {
            int v = e[u][i].first;
            int w = e[u][i].second;
            cout << u << "->" << v << ":" << w << endl;
            dfsShow(v);
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n;
        tot = 1;
        e[1].push_back(dfs());
        dfsShow(1); // 看看树建的对不对
        return 0;
    }
    

    参考代码

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 200; // 节点数量
    int n;
    // --- 建图 ---
    // <子节点 v, 边权 w>
    vector<pair<int, int>> e[MAXN + 5];
    int val[MAXN + 5]; // 叶子结点的画的数量
    int tot;           // 开了多少个节点
    // 返回当前建树后的根节点以及到根节点的边权
    pair<int, int> dfs()
    {
        int u, w, x;
        u = ++tot;
        cin >> w >> x;
        if (x != 0)
            val[u] = x;
        else
        {
            e[u].push_back(dfs());
            e[u].push_back(dfs());
        }
        return {u, w};
    }
    void dfsShow(int u)
    {
        for (int i = 0; i < e[u].size(); i++)
        {
            int v = e[u][i].first;
            int w = e[u][i].second;
            cout << u << "->" << v << ":" << w << endl;
            dfsShow(v);
        }
    }
    // --- treedp 两种写法都能求出答案,但显然求 g 更快---
    int f[MAXN + 5][6005]; // f[u][i] 子树 u 有 i 秒时间的最多偷画数量
    int g[MAXN + 5][2005]; // g[u][i] 子树 u 偷 i 幅画的最少时间
    void dfsDP(int u)
    {
        for (int i = 0; i <= val[u] * 5; i++)
            f[u][i] = i / 5; // 叶子节点的处理
        for (int i = val[u] * 5 + 1; i <= n; i++)
            f[u][i] = f[u][i - 1];
    
        for (int i = 1; i <= 2000; i++)
            g[u][i] = n + 1;
        g[u][0] = 0;
        for (int i = 1; i <= val[u]; i++)
            g[u][i] = i * 5;
        
        for (int i = 0; i < e[u].size(); i++)
        {
            int v = e[u][i].first;
            int w = e[u][i].second;
            dfsDP(v);
            // 求 f
            // 在之前的子树上花费了 j 的时间
            for (int j = n; j >= 0; j--)
                // 在子树 i 上画了 k 的时间
                for (int k = 0; j + k + 2 * w <= n; k++)
                    f[u][j + k + 2 * w] = max(f[u][j + k + 2 * w],
                                              f[u][j] + f[v][k]);
            // 求 g
            for (int j = 2000; j >= 0; j--)
                for (int k = 0; k + j <= 2000; k++)
                {
                    g[u][j + k] = min(g[u][j + k],
                                      g[u][j] + g[v][k] + w * 2);
                }
        }
        /*
        cout << u << ":";
        for (int i = 0; i <= n; i++)
            cout << f[u][i] << " ";
        cout << "\n";
        */
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n;
        tot = 1;
        e[1].push_back(dfs());
        // dfsShow(1);
        dfsDP(1);
        // f 的输出答案
        cout << f[1][n - 1] << "\n"; 
        // g 的输出答案
        for (int i = 2000; i >= 0; i--)
        {
            if (g[1][i] <= n - 1)
            {
                cout << i;
                break;
            }
        }
        return 0;
    }
    

    信息

    ID
    2084
    时间
    1000ms
    内存
    125MiB
    难度
    5
    标签
    递交数
    35
    已通过
    15
    上传者