力扣每日一题(+日常水题|树型dp)

740. 删除并获得点数 - 力扣(LeetCode)

简单分析一下:

每一个数字其实只有2个状态选 or 不

可得预处理每一个数初始状态(不选为0,选为所有x的个数 * x)累加即可

for(auto &x : nums)
   dp[x][1] += x;
       

每选一个树 i 删去 i + 1 和 i - 1

故我们可以将 i - 1视为 i 的父节点, i + 1视为 i 的子节点(此时思路就向树形dp经典题"参加舞会"一样如果i节点参与,其子节点和父节点不参与)

可得

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

再考虑特殊情况:中间断层 1 5 or 任意不连续数字串 

此时对与5 显然 其没有父节点 和 子节点(无法正常转移)

那么倒退4,我们构建4节点,因为其本身不存在选和不选都不影响最终结果

可得

            if(!dp[i][1])
            {
                dp[i][1] = dp[i][0] = mx;
                continue;
            }

由于每一个节点的权值大小不同,对于第i个节点为true的时候有特殊情况(即选的权值不如不选的情况)

可得

                dp[i][1] = max(dp[i][1] + dp[i - 1][0], dp[i - 1][1]);
                dp[i][0] += dp[i - 1][1];

由于题目数据范围为

故进行转移时只用转移1e4次即可 

//using i64 = int64_t;
class Solution {
public:
    const int maxn = 1e4 + 10;
    int dp[10010][2];
    int deleteAndEarn(vector<int>& nums) 
    {
        //视为树形dp(easy版)
        //例如:样例一 == >> 2 3 4
        //样例二 == >> 4 9 4    
        memset(dp, 0, sizeof dp);
        for(auto &x : nums)
        dp[x][1] += x;
        int mx = 0;
        for(int i = 1; i <= 10000; i++)
        {
            if(!dp[i][1])
            {
                dp[i][1] = dp[i][0] = mx;
                continue;
            }
            else
            {
                dp[i][1] = max(dp[i][1] + dp[i - 1][0], dp[i - 1][1]);
                dp[i][0] += dp[i - 1][1];
            }
            mx = max({mx,dp[i][1],dp[i][0]});
        }
        return max(dp[10000][1], dp[10000][0]);
    }
};

 时间复杂度:常数级

2251. 花期内花的数目 - 力扣(LeetCode)

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值