找这个阶段的状态和上各阶段的状态关系
01背包:每件商品只有一件
dp[i][v]:前i件物品恰好装入v的背包中的最大价值
状态:
- 放i,求前i-1件商品恰好装入v-w[i]的背包中的最大价值+第i件商品的价值。
- 不放i,求前i-1件商品恰好装入v的背包中的最大价值。
状态转移方程:
都是求最大价值
dp[i][v]=max( dp[i-1][v] , dp[i-1][v-w[i]]+c[i] )
通过边界dp[0][v]=0(0<=v<=V)
01背包
二维数组的放与不放
int dp[maxn][maxn];
void _01dp()
{
int maxd = 0;
memset(dp, 0, sizeof(dp));
//边界
for (int i = 0; i < V; i++)
{
dp[0][i] = 0;
}
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]);
maxd = max(maxd, dp[i][v]);
}
}
cout << maxd << endl;
}
优化,体积从V-》w[i]逆序发展
;不需要物品i了,直接变为有这个商品的体积,和没有
dp[v]=max ( dp[v],dp[v-w[i]]+c[i])(v=V->w[i],i从1开始)
一维数组的放与不放
int dp[maxn];
void nixudp()
{
memset(dp, 0, sizeof(dp));
//边界
for (int v = 0; v < V; v++)
{
dp[v]= 0;
}
int maxd = 0;
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]);
maxd = max(maxd, dp[v]);
}
}
cout << maxd;
}
用一维数组dp[maxn]体积一定逆序。
5 8
3 5 1 2 2
4 5 2 1 3
完全背包:商品无穷件
放了第i件商品后仍可以继续放第i件商品
- 不放i:求dp[i-1][v]的最大价值
- 放i:求dp[
i
][v-w[i]]得最大价值+c[i]就是当前得最大价值。是i不是i-1因为i可以放很多件
状态转移方程
二维
dp[i][v]=max(dp[i-1][v],dp[i][v-w[i]]+c[i])
一维
dp[v]=max(dp[v],dp[v-w[i]]+c[i])
一维转移方程完全相同,但v是正向枚举(w[i]->V)
for (int i = 1; i <=N ; i++)
{
for (int v=w[i];v<=V;v++)
{
dp[v] = max(dp[v], dp[v - w[i]] + c[i]);
maxd = max(maxd, dp[v]);
}
}
来源:CSDN
作者:曾念念
链接:https://blog.csdn.net/n20164206199/article/details/104678304