題目描述
維克多博士創造了一個裂變反應堆,可取用處於液體狀態的放射性物質。反應堆的容量是V加侖。他有N瓶的放射性液體,每個都有一定的質量和一定的體積。當液體倒入反應堆時,也產生一些單位的能量。現在,維克多想要將能量輸出最大化。但是,有一個限制條件。他研究了原子元素的物理知識和歷史,認識到反應堆內放射性液體的總量不能超過特定的臨界質量M,否則反應就會失控,並引發劇烈的爆炸。
寫一個算法,幫助他從反應堆獲得最大的能量,而不會讓他丟掉性命。
輸入
該函數/方法的輸入包括六個參數——
reactorCap,一個整數,表示反應堆的容量(V);
numberOfRadLiquid,一個整數,表示現有小瓶的數量(N);
criticalMass,一個整數,表示反應堆的最大臨界質量(M);
volumes,一個整數列表,按順序表示N份放射性液體的體積;
masses,一個整數列表,按順序表示N份放射性液體的質量;
energies,一個整數列表,按順序表示N份放射性液體產生的能量。
輸出
返回一個整數,表示可在給定的約束條件下從反應堆中產生的最大能量。
約束條件
1=<numberOfRadLiquid<=10^4
思路
這是一道二維的01揹包問題。
代碼
public class MaxEnergy {
public static int maxEnergyGenerate(int reactorCap,int numberOfRadLiquid,int criticalMass,
int[] volumes,int[] masses,int[] energies){
//energy數組的項energy[i][j]代表當前臨界容量(i)和臨界質量(j)下的最大能量
int[][] energy = new int[reactorCap+1][criticalMass+1];
for(int i=0;i<numberOfRadLiquid;i++){
for(int v=reactorCap;v>=volumes[i];v--){
for(int m=criticalMass;m>=masses[i];m--){
energy[v][m] = Math.max(energy[v-volumes[i]][m-masses[i]]+energies[i],energy[v][m]);
}
}
}
return energy[reactorCap][criticalMass];
}
public static void main(String[] args){
int reactorCap = 250;
int numberOfRadLiquid = 5;
int criticalMass = 25;
int[] volumes = {30,40,50,60,70};
int[] masses = {7,8,9,10,11};
int[] energies = {300,400,500,600,700};
int result = maxEnergyGenerate(reactorCap,numberOfRadLiquid,criticalMass,volumes,
masses,energies);
System.out.println(result);
}
}
擴展
如果需要依次輸出放入的放射性液體,如依次輸出所放入的放射性液體的能量,則代碼如下:
public class MaxEnnergy_3 {
public static int maxEnergyGenerate(int reactorCap,int numberOfRadLiquid,int criticalMass,
int[] volumes,int[] masses,int[] energies){
//energy數組的項energy[i][j]代表當前臨界容量(i)和臨界質量(j)下的最大能量
int[][][] energy = new int[numberOfRadLiquid+1][reactorCap+1][criticalMass+1];
for(int i=1;i<=numberOfRadLiquid;i++){
for(int v=reactorCap;v>=volumes[i-1];v--){
for(int m=criticalMass;m>=masses[i-1];m--){
energy[i][v][m] = Math.max(energy[i-1][v-volumes[i-1]][m-masses[i-1]]+energies[i-1],energy[i-1][v][m]);
}
}
}
int v= reactorCap;
int m = criticalMass;
for(int i=numberOfRadLiquid;i>0;i--){
if(energy[i][v][m]>energy[i-1][v][m]){
System.out.println(energies[i-1]);
v -= volumes[i-1];
m -= masses[i-1];
}
if(v<=0 || m<=0) break;
}
return energy[numberOfRadLiquid][reactorCap][criticalMass];
}
}