Nazrin the Greeeeeedy Mouse 2023牛客暑期多校训练营5 H

登录—专业IT笔试面试备考平台_牛客网

题目大意:有n个物品,m个背包,给出每个物品的重量和价值,以及每个背包的容量,背包按容量从小到大排序,每次取最靠前的背包,也只能按顺序取物品,每个物品可以选择拿或不拿,如果不拿,所有其他背包都不能拿,问能获得的最大价值是多少

1<=n<=200;1<=m<=1e5;1<=wi<=200

思路:首先,当m>n时,因为背包是按容量排序好的,所以只有最后n个背包才有用,如果后n个里面有没用的背包,那前边的一定更没有,所以背包总量最多也就是200个

那么我们令dp[i][j][k]表示当前处理第i件物品,第j个背包中装了重量为k的物品的最大价值,我们可以用与01背包相同的转移方程求出每个背包拿前i个商品的最优方案,又因为下一个背包是接着上一个背包取完的地方拿的,所以每个物品对所有背包求完后,第j个背包获取的最大价值可以传递给dp[j+1][0],也就是下一个背包不需要容量就可以获得这么多价值,最后的最终状态就是最后一个背包获取的最大价值,取其中的最大值即为答案

//#include<__msvc_all_public_headers.hpp>
#include
using namespace std;
const int N = 205;
paira[N];
int dp[N][N];
int b[N];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i].first >> a[i].second;
	}
	int tot = 0;
	for (int i = 1; i <= m; i++)
	{
		int x;
		cin >> x;
		if (i >= m - n + 1)
		{//只有最后n个物品有用
			b[++tot] = x;
		}
	}
	if(m>n)
		m = n;
	for (int i = 1; i <= n; i++)
	{//遍历每个物品
		for (int j = 1; j <= m; j++)
		{//遍历每个背包
			for(int k=b[j];k>=a[i].first;k--)
			{//取不同重量的物品
				dp[j][k] = max(dp[j][k], dp[j][k - a[i].first] + a[i].second);
			}
		}
		for (int j = 1; j <= m - 1; j++)
		{
			for (int k = 0; k <= b[j]; k++)
			{
				dp[j + 1][0] = max(dp[j + 1][0], dp[j][k]);//将每个背包获取的最大价值传给下一个背包
			}
		}
	}
	int ma = 0;
	for (int i = 0; i <= b[m]; i++)
	{
		ma = max(ma, dp[m][i]);
	}
	cout << ma << endl;
	return 0;
}

你可能感兴趣的:(dp,算法,c++)