2019中興筆試算法題之維克多博士的裂變反應堆[二維01揹包問題][java]

題目描述

維克多博士創造了一個裂變反應堆,可取用處於液體狀態的放射性物質。反應堆的容量是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];
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章