C++:动态规划(2)背包问题

帅比萌擦擦* 提交于 2020-03-06 01:50:07

找这个阶段的状态和上各阶段的状态关系

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]);
	}
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!