笔试题26——二重01背包问题

题目描述:
维克多博士创造了一个裂变反应堆,可取用处于液体状态的放射性物质。反应堆的容量是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。
核心代码如下:

#include 
#include 
#include 
#include 
using namespace std;
int dp[601][601][601];
int dp2[601][601];
//memset(dp, 0, sizeof(dp));
int maxEnergyGenerate(int V, int N, int M, int* volumes, int* masses, int* energies) {
	for (int i = 1; i <= N; i++) { //小瓶容量		
		for (int j = V; j >= 0; j--) {  //反应器容量
			for (int k = M; k >= 0; k--) {  //最大临界质量
				if (j - volumes[i - 1]<0 || k - masses[i - 1]<0) 
					dp[i][j][k] = dp[i - 1][j][k];
				else 
					dp[i][j][k] = max(dp[i - 1][j][k], dp[i - 1][j - volumes[i - 1]][k - masses[i - 1]] + energies[i - 1]);
			}
		}
	}

	return dp[N][V][M];
}

int mytest(int v, int n, int m, int* volumes, int* masses, int* energies) {
	for (int i = 1; i <= n; i++) {
		for (int j = v; j >= volumes[i - 1]; j--) {
			for (int k = m; k >= masses[i - 1]; k--) {
				dp2[j][k] = max(dp2[j][k], dp2[j - volumes[i - 1]][k - masses[i - 1]] + energies[i - 1]);
			}
		}
	}
	return dp2[v][m];
}

int main() {

	int v = 100, n = 5, m = 15;
	int volumes[] = { 50,40,30,20,10 };
	int masses[] = { 1,2,3,9,5 };
	int energies[] = { 300,480,270,200,180 };
	
	cout << maxEnergyGenerate(v, n, m, volumes, masses, energies) << endl;
	cout << "new: " << endl;
	cout << mytest(v, n, m, volumes, masses, energies) << endl;
	return 0;
}

你可能感兴趣的:(笔试题)