【LeetCode刷题记录/Python】刷题记录之被动态规划折磨一整天,已破防

题目描述

执行操作可获得的最大总奖励 I

给你一个整数数组 rewardValues,长度为 n,代表奖励的值。
最初,你的总奖励 x 为 0,所有下标都是 未标记 的。你可以执行以下操作 任意次 :
从区间 [0, n - 1] 中选择一个 未标记 的下标 i。
如果 rewardValues[i] 大于 你当前的总奖励 x,则将 rewardValues[i] 加到 x 上(即 x = x + rewardValues[i]),并 标记 下标 i。
以整数形式返回执行最优操作能够获得的 最大 总奖励。

示例

输入:rewardValues = [1,1,3,3]

输出:4

解释:

依次标记下标 0 和 2,总奖励为 4,这是可获得的最大值。

提示:
1 <= rewardValues.length <= 2000
1 <= rewardValues[i] <= 2000

关于动态规划

这两天在看算法书,动态规划篇中以背包问题为例。但与这题有一点不同,背包问题中使用二维数组,其含义是,对于一个给定的空间,可以通过遍历数组使得让这一个空间利用率最高。如何实现?简单来说就是:
d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − s p a c e [ i ] ] + v a l u e [ i ] ) dp[i][j]=max(dp[i-1][j], dp[i-1][j-space[i]]+value[i]) dp[i][j]=max(dp[i1][j],dp[i1][jspace[i]]+value[i])
其中, s p a c e [ i ] space[i] space[i]为当前元素占用空间, v a l u e [ i ] value[i] value[i]为当前元素价值。
也许再看完两本算法书,我会再写一篇文章讲讲我对动态规划的看法。
这一题不需要用到二维数组,而且这一题的思路与上述差异也较大。我们接下来分析。

题目分析

首先对数组进行排序。

我们从最小的开始,再看看第二小的(我们假设每个元素不相同),如果数组就这两个元素,那直接返回求和数就行。

但当出现第三个元素之后,考虑的就多了。

首先要判断,第三个元素是不是大于前两个元素之和?如果大于,那求和就行。
但如果小于等于,那么很显然就要求和第2,3个元素。

接下来我们引入第四个元素,事情变得更复杂了!

文字叙述已经有点困难了,此处请用手算。

这时我们引入一个二维坐标轴,横轴坐标是总和(这个总和可以取很大,但必须大于所有元素的和),纵轴是数组元素的索引,记录着这个元素的值。(可以在坐标轴旁边标上值!)
横轴是从1开始的(1,2,3…),一直到那一个总和。
我们假装 ( 1 , 1 ) (1,1) (1,1)是坐标原点,从这一行开始往右写,如果目前有可以达到横坐标值的取法,那就在那里填上1。比如说我们第一个元素是1,那么我们就在 ( 1 , 1 ) (1,1) (1,1)填上1,但如果我们第一个元素是2,那 ( 1 , 1 ) (1,1) (1,1)就应该填0了,因为取不到。同理,当第一个元素是1,那么 ( 2 , 1 ) (2,1) (2,1)处就要填0了,而且这一行其他的坐标都要填上0。

写完了第一行,我们开始写第二行。假如第二个元素是3。我们从 ( 1 , 2 ) (1,2) (1,2)开始,这个坐标可以填1吗?答案是可以,因为第一个元素是1,使目前所有元素总和为1是可能的,也就是说,其实我们定义数组的时候只需要一维就可以了。然后是 ( 2 , 2 ) (2,2) (2,2),这个点不能填1。(2,3)就可以了,同理(2,4)也可以,因为1+3=4,然后(2,5)又不行了。

尝试自创一个数组,然后按这种方式填表。

我们就会发现:如果一个元素为x,目前的和(就是横坐标)是sum,如果sum-x<x,那么这个点能否填1,就只和sum-x的值有关! 因为如果sum-x是1,就意味着前面有某种方法能够使总和为这个值,而这个值又符合比x小的条件,那么我们加上x就是目前的最佳情况!!!

很烂的题解

rewardValues = [6,13,9,19]  // 题目给出
s = 2*max(rewardValues)  
dp = [0]*s  
rewardValues.sort() 
sort = rewardValues

for i in range(s):
    if sort[0] == i:
        dp[i] = 1
    else:
        dp[i] = 0
// 初始化,没用的代码
for i in range(1, len(rewardValues)):
    for j in range(s):
        if sort[i] == j:
            dp[j] = 1   // 继承上一个节点的值
        elif (sort[i] < j) and (j-sort[i] < sort[i]) and dp[j-sort[i]] == 1:
            dp[j] = 1

for i in range(s-1, 0, -1):
    if dp[i] == 1:
        res = i
        break
print(res)

总结

这道题用0和1的flag判断能不能取到值,与我最开始想的用二维数组的每个节点记录最大值有点出入,也是在这里卡了很久。
第一次比较系统地接触算法,第一次了解到动态规划,以上只是一点浅显的看法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值