今日复习内容:做真题 + 复习动态规划
完全背包问题是背包问题的一个重要变体。
1.问题描述
给定一个背包,容量为C,一组物品,每个物品有自己的重量wi和价值vi,完全背包问题要求在不超过背包容量的情况下,放入物品的总价值最大。
2.动态规划解法
使用动态规划是解决完全背包问题的常用方法。定义状态dp[i][j]表示前i个物品,在背包容量为j时能够获得的最大价值。
状态转移方程为dp[i][j] = max(dp[i - 1][j],dp[i][j - wi] + vi)
这里的状态转移方程与0-1背包类似,但不同之处在于在计算第i个物品时,背包容量可以多次减去wi。
3.时间复杂度
动态规划解法的时间复杂度为O(NC),其中N是物品的数量,C是背包的容量。因为对于每个物品和每个背包容量都需要计算状态,所以是一个二维的动态规划问题。
例题1:小明的背包2
题目描述:
小明有一个容量为V的背包。
这天他去商场购物,商场一共有N种物品,第i种物品的体积为wi,价值为vi,每种物品都有无限多个。
小明想知道在购买的物品总体积不超过V的情况下所能获得的最大价值是多少,请你帮他算算。
输入描述:
输入第一行包含两个正整数N和V,表示商场的物品数量和小明的背包容量。
第2至N + 1行包含两个正整数w和v,表示物品的体积和价值。
1 <= N <= 10^3,1 <= V <= 10^3,1 <= wi,vi <= 10^3.
输出描述:
输出一行整数表示小明所能获得的最大价值。
参考答案:
N,V = map(int,input().split())
dp = [[0] * (V + 1) for i in range(N + 1)]for i in range(1,N + 1):w,v = map(int,input().split())for j in range(V + 1):if j < w:dp[i][j] = dp[i - 1][j]else:dp[i][j] = max(dp[i - 1][j],dp[i][j - w] + v)print(dp[N][V])
运行结果:
我还可以把它优化一下:
N,V = map(int,input().split())
dp = [0] * (V + 1)
for i in range(1,N + 1):w,v = map(int,input().split())for j in range(w,V + 1):dp[j] = max(dp[j],dp[j - w] + v)print(dp[V])
多重背包问题是背包问题的另一种变体,与0-1背包问题和完全背包问题不同,多重背包问题允许每种物品放入背包的数量有限制。
1.问题描述
给定一个容量为C的背包,一组物品,每个物品都有自己的重量wi,价值vi和数量限制ni,多重背包问题要求在不超过背包容量的情况下,放入物品的总价值最大。
2.动态规划解法
多重背包问题也可以使用动态规划来解决,但相比于完全背包问题,状态转移方程需要更多的考虑。
定义状态dp[i][j]表示前i个物品,在背包容量为j时能够获得的最大价值。
状态转移方程为dp[i][j] = max(dp[i - 1][j - k * wi] + k * vi),其中k的取值范围是 0 <= k <= ni,表示第i个物品放入背包的数量。
例题2:小明的背包3
题目描述:
小明有一个容量为V的背包。
这天他去商场购物,商场一共有N件商品,第i件物品的体积为wi,价值为vi,数量为si。
小明想知道在购买的物品的总体积不超过V的情况下所能获得的最大价值是多少,请你帮他算算。
输入描述:
输入第一行包含两个正整数N,V,表示商场的商品数量和背包容量。
第2至N + 1 行包含三个正整数w,v,s,表示物品的体积和价值。
1 <= N <= 10^2,1 <= V <= 2 * 10^2,1 <= wi,vi,si <= 2 * 10^2
输出描述:
输出一行整数表示小明所能获得的最大价值。
参考答案:
N,V = map(int,input().split())
dp = [[0] * (V + 1) for i in range(N + 1)]
for i in range(1,N + 1):w,v,s = map(int,input().split())for j in range(V + 1):for k in range(min(s,j // w) + 1):dp[i][j] = max(dp[i][j],dp[i - 1][j - k * w] + k * v)print(dp[N][V])
运行结果:
二维费用背包问题是背包问题的一个扩展,与经典的0-1背包问题,完全背包问题和多重背包问题不同,它增加了物品的两个维度的费用。
1.问题描述
给定一个背包容量C,一组物品,每个物品具有两个维度的费用wi和ci,以及对应的价值vi。二维费用背包问题要求在不超过背包容量的情况下,放入物品的总价值最大。
2.动态规划解法
二维费用背包问题可以用动态规划来解决。定义状态dp[i][j][k]表示前i个物品,在背包容量为j时和第二维费用为k时获得的最大价值。
状态转移方程为dp[i][j][k] = max(dp[i - 1][j][k],dp[i - 1][j - wi][k - ci] + vi)
这里的状态转移方程表示在选择放入第i个物品时,可以选择放入或不放入,并考虑背包容量和第二维费用的限制。
3.时间复杂度
动态规划解法的时间复杂度是O(NCM),其中N是物品的数量,C是背包容量的上限,M是第二维费用的上限。因为需要考虑每个物品,每个背包容量和每个第二维费用的情况,所以是一个三维的动态规划问题。
例题3:小蓝的神秘行囊
题目描述:
小蓝是一名著名的探险家,他即将踏上一场寻宝的冒险旅程,他的目的是寻找和收集各种神秘的宝物。他有一个神秘的行囊,能够装载各种物品。然而,这个行囊有一个特殊的规定:它的最大容量是V,并且他能承载的最大重量是M。
小蓝来到一个古老的城堡,里面有N件神秘的宝物,每件宝物只能被取走一次,每件宝物都有特定的体积vi,重量mi和价值wi。
面对眼前的宝物,小蓝需要做出决定:将哪些宝物放入他的行囊,使得宝物的总体积不超过行囊的体积,总重量不超过行囊的最大承重量,且价值总和最大。
你的任务是帮助小蓝决定应该选择哪些宝物,并输出这些宝物的最大价值和。
输入描述:
第一行是3个正整数N,V,M,用空格隔开,分别表示宝物的数量,行囊的容量和行囊所能承载的最大重量。
接下来的N行,每行有3个整数vi,mi,wi,用空格隔开,分别表示每个宝物的体积,重量和价值。
数据范围保证:0 < N <= 1000,0 < V,M <= 100,0 < vi,wi <= 100,0 < wi <= 1000。
输出格式:
输出一个整数,表示可以装入行囊的宝物的最大总价值。
参考答案:
N,V,M = map(int,input().split())
dp = [[0] * (M + 1) for i in range(V + 1)]
for i in range(N):v,m,w = map(int,input().split())for j in range(V,v - 1,-1):for k in range(M,m - 1,-1):dp[j][k] = max(dp[j][k],dp[j - v][k - m] + w)print(dp[V][M])
运行结果:
分组背包是背包问题的一种变体,与0-1背包问题,完全背包问题等有所不同。在分组背包问题中,物品被视为若干组,每组中的物品只能选择一个放入背包。
1.问题描述
给定一个容量为C的背包,若干组物品,每组中的物品有自己的重量wi和价值vi,每组物品只能选择一个放入背包。分组背包问题要求在不超过背包容量的情况下,放入背包的总价值最大。
2.动态规划解法
分组背包问题同样可以使用动态规划来解决。定义dp[i][j]表示前i组物品,在背包容量为j时能够获得的最大价值。
价值转移方程为:
dp[i][j]=max(dp[i−1][j],max(k=1到ni)dp[i−1][j−wi,k]+vi,k)
其中ni表示第i组物品的数量,wi,k表示第i组中第k个物品的重量,vi,k表示第i组中第k个物品的价值。
3.时间复杂度
动态规划的时间复杂度是O(GC),其中G是组数,C是背包的容量。因为需要考虑每组物品和每个背包容量的情况,所以是一个二维的动态规划问题。
例题4:小明的背包5
题目描述:
小明有一个容量为V的背包。
这天他去商场购物,商场一共有N组物品,第i组里有si件物品,物品的体积为w,价值为v,对于每一组只能购买一件物品。
小明想知道在购买的物品总体积不超过V的条件下所能获得的最大价值是多少,请你帮他算算。
输入描述:
输入第一行包含两个正整数N和V,表示商场物品的数量和小明背包的容量。
接下来有N组数据,对于每组数据的输入如下:
第一行输入一个整数s,表示该组的物品个数;
接下来s行每行包含两个整数w,v,表示物品的体积和价值。
1 <= N,V <= 10^2,1 <= s <= 10^2,1 <= w,v <= 10^3
输出描述:
输出一行整数表示小明所能获得的最大价值。
参考答案:
N,V = map(int,input().split())
dp = [[0] * (V + 1) for i in range(N + 1)]
for i in range(1,N + 1):s = int(input())for _ in range(s):w,v = map(int,input().split())for j in range(V + 1):if j < w:dp[i][j] = max(dp[i][j],dp[i - 1][j])else:dp[i][j] = max(dp[i][j],dp[i - 1][j],dp[i - 1][j - w] + v)print(dp[N][V])
运行结果:
OK,这篇就写到这里,我得加快一点复习速度了,下一篇继续!