动态规划--美丽的项链

一、01背包问题

题目:假设你是一个小偷,背着一个可以装4磅的背包。你可以盗窃的商品有如下3件,其中每件商品只能选择依次:

商品名称商品价值(美元)商品重量(磅)
音响30004
笔记本电脑20003
吉他15001

解题思路:
  这是一个很典型的动态规划的例子,每个动态规划的算法都从一个网格开始。根据题意可以建立如下网格。
  
            各列为不同的容量(1-4)的背包,各行为可选择的商品

1234
吉他1500150015001500
音响1500150015003000
笔记本电脑1500150020003500

其中网格填写步骤如下所示:
1)数组设定。设网格为一个二维数组DP[商品种类数][背包容量]。其中DP[i][j]代表前 i 种商品放入容量为 j 背包的最大价值。
2)初始化第一行。即DP[0][0]到DP[0][3]。此时,我们只能选择吉他。那么当背包容量为1到4时,只有一种选择方案,就是吉他。所以第一行所有价值都是吉他的价值1500美元,占用容量1磅。
3)计算后面几行。
DP[i][j] = max(A,B)
A = DP[i-1][j] ;B = 当前商品的价值+剩余空间的价值=当前商品的价值+DP[i-1][j-当前商品的重量]

二、美丽的项链
在这里插入图片描述在这里插入图片描述
解题思路:
使用二维数组进行求解。设dp[i][j]代表前i+1种珠宝凑成j颗珠宝的项链。

012345
第0种宝石111100
第1种宝石123432
第2种宝石136101212

如果已知前i种宝石凑成0-j颗珠宝的项链,那么就在此基础上,加上第i+1种珠宝凑成j颗珠宝项链。每种宝石都有最低使用值和最高使用值。此时可以推出一个公式
                dp[i][j] = dp[i-1][j-ri]+ dp[i-1][j-ri+1]+ …+dp[i-1][j-li]
如:第一种宝石行,dp[1][3]=df[0][3-0]+dp[0][3-1]]+dp[0][3-2]+dp[0][3-3]=4。即可以表示为,
已知第0种宝石,凑成3颗宝石的方法数,此时第1种宝石不添加,凑成3颗宝石的方法数。
已知第0种宝石,凑成2颗宝石的方法数,此时第1种宝石添加1颗,凑成3颗宝石的方法数。
已知第0种宝石,凑成1颗宝石的方法数,此时第1种宝石添加2颗,凑成3颗宝石的方法数。
已知第0种宝石,凑成0颗宝石的方法数,此时第1种宝石添加3颗,凑成3颗宝石的方法数。
将上面四项相加,即得到dp[1][3]。同理,其他的依照上诉告时进行确定。需要注意的是,添加的宝石有最小和最大的限制。

代码(python3):

#coding:utf-8
n,m = map(int,input().split())
L=[]
R=[]
for i in range(n):
    li,ri = map(int,input().split())
    L.append(li)
    R.append(ri)

dp = [[0 for i in range(m+1)] for j in range(n)]

#初始化第一行
for i in range(L[0],R[0]+1):
    dp[0][i] = 1

#剩余其他行使用公式进行计算
for i in range(1,n):
    for j in range(m+1):
        left = max(0,j-R[i])
        right = max(0,j-L[i])
        for l in range(left,right+1):
            dp[i][j] += dp[i-1][l]
print(dp)
print(dp[n-1][m])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值