leetcode 2920. 收集所有金币可获得的最大积分

题目:2920. 收集所有金币可获得的最大积分 - 力扣(LeetCode)

看数据范围是需要O(n*log(n))的算法。可以用dfs+记忆化搜索。

考虑到coins[i]的范围是[0, 10000],最多除个十几次2就变成0了。所以用w[i][j]表述节点i在除以j次后,以i为根节点的子树的最大值,来进行dfs的记忆化。

struct Node {
    vector<Node*> links;
    vector<Node*> children;
    int idx;
    int* val = new int[16];
    int* w = new int[16];
    bool* f = new bool[16];
    Node(int idx, int v) {
        this->idx = idx;
        memset(f, 0, 16);
        val[0] = v;
        for (int i = 1; i < 16; i++) {
            val[i] = val[i - 1] / 2;
        }
    }
    void Build(int parent = -1) {
        for (int i = 0; i < links.size(); i++) {
            if (links[i]->idx != parent) {
                children.push_back(links[i]);
                links[i]->Build(idx);
            }
        }
    }
    int DFS(int t, int k) {
        if (t >= 16) {
            return 0;
        }
        if (f[t]) {
            return w[t];
        }
        int a = (t < 16 ? val[t] : 0) - k;
        for (int i = 0; i < children.size(); i++) {
            a += children[i]->DFS(t, k);
        }
        int b = t < 15 ? val[t + 1] : 0;
        for (int i = 0; i < children.size(); i++) {
            b += children[i]->DFS(t + 1, k);
        }
        f[t] = true;
        w[t] = max(a, b);
        return w[t];
    }
};
class Solution {
public:
    int maximumPoints(vector<vector<int>>& edges, vector<int>& coins, int k) {
        vector<Node*> tree;
        for (int i = 0; i < coins.size(); i++) {
            tree.push_back(new Node(i, coins[i]));
        }
        int a, b;
        for (int i = 0; i < edges.size(); i++) {
            a = edges[i][0];
            b = edges[i][1];
            tree[a]->links.push_back(tree[b]);
            tree[b]->links.push_back(tree[a]);
        }
        tree[0]->Build();
        
        return tree[0]->DFS(0, k);
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值