动态规划:背包问题

一:多阶段动态规划问题

  1. 一类动态规划可解的问题,它可以描述成若干个有序的阶段,且每个阶段的状态只和上一个阶段的状态有关。这类问题称为多阶段动态规划问题。

二:01背包问题

01背包问题是这样的:

有n件物体,每件物品的重量为w[i],价值为c[i]。现有一个容量为V的背包,问如何选取背包物品放入背包,使得背包内物品的总价值最大。没件物品都只有1件。

样例:

5 8 //n ==5,v ==8
3 5 1 2 2 //w[i]
4 5 2 1 3 //c[i]

如果采用暴力枚举每一件物品放或者不放进书包,显然每件物品都有两种选择,因此复杂度为O(2^n).使用动态规划可以将复杂度降为O(nV)。

令dp[i][v]表示前i件物品恰好装入容量为v的背包中所能获得的最大价值.

考虑第i件物品的选择策略:

不放第i件物品的,那么问题转换为前i-1件物品恰好装入容量为v的背包中所能获得的最大价值,也即dp[i-1][v].
放第i件物品,那么问题转换为前i-1件物品恰好装入容量为v-w[i]的背包中所能获得的最大价值dp[i-1][v-w[i]]+c[i].
由于只有两种策略,且要求获得最大价值,

因此状态转移方程:

dp[i][v]=max{dp[i-1][v],dp[i-1][v-w[i]]+c[i]} (1<=i<=n,w[i]<=v<=V)

dp[i][v]只与之前的状态dp[i-1][]有关,所以可以枚举i从1到n,所以可以写出代码

for(int i=1;i<=n;i++)
 {
     
 		for(int v= w[i];v<=V;v++)
 		{
     
 			dp[i][v]=max{
     dp[i-1][v],dp[i-1][v-w[i]]+c[i]};
 		}
 }

优化空间复杂度:
状态转移方程可以写为dp[v]=max(dp[v],dp[v-w[i]]+c[i])

for (int i=1;i<=n;i++)
{
     
	for(int v=V;v>=w[i];v--)
	{
     
		dp[v]=max{
     dp[v],dp[v-w[i]]+c[i]};
	}
}

这样01背包就可以用一维数组表示解决了,空间复杂度为O(V)。
状态转移方程为:dp[v]=max{dp[v],dp[v-w[i]]+c[i](1<=i<=n,w[i]<=v<=V)
边界:dp[v]=0(0<=v<=V)

三: 完全背包问题

有n种物品,每种物品的单件重量为w[i],价值为c[i].现在一个容量为V的背包,问如何选取物品放入背包,使得背包内物品的总价值最大。其中每件物品都有无穷件。

和01背包问题一致,对第n件物品而言:

  1. 不放第i件物品,那么dp[i][v]=dp[i-1][v],这步跟01背包问题一致。
  2. 放第i件物品。这里的处理和01背包有所不同,因为01背包的每个物品只能选择一个,因此选择第i件物品就意味着必须转移dp[i-1][v-w[i]]这个状态;但是完全背包不同,完全背包如果选择的放第i件物品之后并不是转移到dp[i-1][v-w[i]],而是转移到dp[i][v-w[i]],放了第i件物品还可以放第i件物品,直到第二维的v-w[i]无法保持大于等q于0为止。

由上可以得出状态转移方程:dp[i][v]=max(dp[i-1][v],dp[i][v-w[i]]+c[i])

你可能感兴趣的:(算法,动态规划)