中兴--维克多博士问题(背包问题升级版)

题目描述:

维克多博士创造了一个裂变反应堆,可取用处于液体状态的放射性物质。反应堆的容量是V加仑。他有N瓶的放射性液体,每个都有一定的质量和一定的体积。当液体倒入反应堆时,也产生一些单位的能量。现在,维克多想要将能量输出最大化。但是,有一个限制条件。他研究了原子元素的物理知识和历史,认识到反应堆内放射性液体的总量不能超过特定的临界质量M,否则反应就会失控,并引发剧烈的爆炸。写一个算法,帮助他从反应堆获得最大的能量,而不会让他丢掉性命。

输入:
该函数/方法的输入包括六个参数------
reactorCap,一个整数,表示反应堆的容量(V);
numberOfRadLiquid,一个整数,表示现有小瓶的数量(N);
criticalMass,一个整数,表示反应堆的最大临界质量(M);
volumes,一个整数列表,按顺序表示N份放射性液体的体积;
masses,一个整数列表,按顺序表示N份放射性液体的质量;
energies,一个整数列表,按顺序表示N份放射性液体产生的能量。

输出:
返回一个整数,表示可给定的约束条件下从反应堆中产生的最大能量。

示例:
输入:
reactorCap=100
numberOfRadLiquid=5
criticalMass=15
volumes=[50,40,30,20,10]
masses=[1,2,3,9,5]
energies=[300,480,270,200,180]
输出:
960

解释:
通过选择1、2、5号瓶中的液体,产生的能量=300+480+180=960。
这种液体组合产生的总体积=50+40+10=100,不大于reactorCap,造成反应堆中的总质量=1+2+5=8,不大于criticalMass。

解题思路:这是一个有两个限制条件的0-1背包问题,0-1背包问题可以参考我的另一篇博文:0-1背包问题,这里只需将一个限制条件的二维动态规划表变成一个三维动态规划表。

int maxEnergyGenerate(int reactorCap, int numberOfRadLiquid, int criticalMass, int *volumes, int *messes, int *energies)
{
	vector<vector<vector <int>>> maxValue;
	vector<vector <int>> tmpTmp;
	vector<int> tmp;
	for (int i = 0; i < numberOfRadLiquid + 1; i++)
	{
		for (int j = 0; j < reactorCap + 1; j++)
		{
			for (int k = 0; k < criticalMass + 1; k++)
			{
				tmp.push_back(0);
			}
			tmpTmp.push_back(tmp);
			tmp.clear();
		}
		maxValue.push_back(tmpTmp);
		tmpTmp.clear();
	}

	for (int i = 1; i <= numberOfRadLiquid; i++)
	{
		for (int j = 1; j <= reactorCap; j++)
		{
			for (int k = 1; k <= criticalMass; k++)
			{
				if (i == 1)
				{
					if ((volumes[i - 1] <= j) && (messes[i - 1] <= k))
					{
						maxValue[i][j][k] = energies[i - 1];
					}
					else
					{
						maxValue[i][j][k] = 0;
					}
				}
				else
				{
					int topValue = maxValue[i - 1][j][k];  // 上一个网格的值
					int thisValue = ((volumes[i - 1] <= j) && (messes[i - 1] <= k) ?       // 当前商品的价值 + 剩余空间的价值
						((k - messes[i - 1] > 0)&&(j - volumes[i - 1] > 0) ? energies[i - 1] + maxValue[i - 1][j - volumes[i - 1]][k - messes[i - 1]] :energies[i - 1])
						: topValue);
					// 返回 topValue和thisValue中较大的一个
					maxValue[i][j][k] = (topValue > thisValue ? topValue : thisValue);
				}
			}
		}
	}
	vector<bool> result;
	for (int i = 0; i < numberOfRadLiquid; i++)
	{
		result.push_back(false);
	}
	for (int i = numberOfRadLiquid, j = reactorCap, k = criticalMass; i > 0; i--)
	{
		if (maxValue[i][j][k] > maxValue[i - 1][j][k])
		{
			result[i - 1] = true;
			j = j - volumes[i - 1];
			k = k - messes[i - 1];
		}
	}
	int sum = 0;
	for (int i = 0; i < result.size(); i++)
	{
		if (result[i])
		{
			sum += energies[i];
		}
	}
	return sum;
}
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值