算法与设计分析作业2(动态规划)

算法与设计分析作业2(动态规划)


1 Largest Divisible Subset

Given a set of distinct positive integers, find the largest subset such that every pair (Si,Sj) of elements in this subset satisfies:Si%Sj = 0 or Sj%Si = 0.

The optimal substructure and DP equation

首先将数组升序排序,这样我们就可以把较大的问题转换成较小的问题。dp[i]表示以dp[i]为最大数的符合要求子集的最大元素个数,max[i]表示到i位置为止符合要求子集的最大元素个数。因此该题可以将n个元素的符合要求的最大子集转变为前n-1个元素符合要求的最大子集(直至只剩下一个元素)。递推式为:1 1.2

另外我们利用pre[]数组记录前一个可整除的值的下标,最后根据这些下标找到自己元素。

Pseudo-code
# @param {Integer[]} nums
# @return {Integer[]}
function largest_divisible_subset(nums)
      if nums.length==0 then return [] end  
      nums数组升序排序
      建立dp数组并填充1
      建立max数组并填充1
      建立pre数组并填充为自己的下标
      for i in 1...nums.length
        for j in 0...i
          if nums[i]%nums[j]==0 && dp[i]<dp[j]+1
            dp[i]=dp[j]+1
            pre[i]=j
          end
        end
        max[i]=max(dp[i],max[i-1])
      end
      建立子集subset
        取max数组中第一个最大值的下标x
      while pre[x]!=x
        根据下标指示将元素nums[x]加入到子集subset中
        x=pre[x]
      end
      将最后一个元素nums[x]加入到子集subset中
      返回自己subset
end
Prove the correctness

首先该问题包含最优子结构的性质,我们可以将n个元素的符合要求的最大子集转变为前n-1个元素符合要求的最大子集(直至只剩下一个元素)。其次该问题包含重叠子性质,在解题过程中许多子问题需要重复计算,比如计算dp[3]是需要计算dp[2]+1,计算dp[4]需要计算dp[2]+1,那么dp[2]就是需要重复计算的,因此可以用”备忘录”将其记录。综上该题用动态规划是正确的。

The complexity of your algorithm

首先排序算法的复杂度为O(nlogn),求dp过程中的循环次数为n*(n-1)/2,复杂度为O(n2),最后回溯求子集的复杂度为O(n),因此最后的时间复杂度为O(n2)。

2 Money robbing

A robber is planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

  1. Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
  2. What if all houses are arranged in a circle?
The optimal substructure and DP equation

对于问题1,dp[i]表示从0~i家房子能抢到钱的最大数目,对于每一个房子,我们可以做一个决策,抢钱或者不抢钱。若是不抢钱,我们在该房子位置能抢到的最多钱就是前一个房子的能抢到的最多钱dp[i]=dp[i-1],若是抢钱,我们在该房子位置能抢到的最多钱就是当前房子能抢到钱加上前二个房子能抢到的最多钱dp[i]=dp[i-2]+nums[i]。两种决策的最大值就是该房子位置能抢到的最多钱。因此递推式为: 2

对于问题2,递推式是不变的,由于房子形成一个环,所以第一个房子和最后一个房子不能同时抢,所以只能抢第一个房子或者抢最后一个房子,因此我们只需要求0~nums.length-2号房子能抢到的最多钱和1~nums.length-1号房子能抢到的最多钱,两者比较求最大值。

Pseudo-code
# @param {Integer[]} nums
# @return {Integer}
# question 1:
function rob(nums)
    if nums.length==0 
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值