1. 程式人生 > >一維,多維揹包問題(體積,重量)

一維,多維揹包問題(體積,重量)

這裡列出了在只存在體積和存在體積,重量兩種情況下揹包問題的解決方法

第一種情況:

某人從外地販貨物回本省出售

有3種貨物:

A貨物,單個重量80KG,單個價值60塊

B貨物,單個重量50KG,單個價值50塊

C貨物,單個重量50KG,單個價值40塊

最大載重100KG,請用遞迴的演算法求出最優解

 
public class Main_2d {
    public static int[][] m = new int[4][101];
    public static int[] v_arr = new int[]{80,50,50};//物品體積
    public static int[] t_arr = new int[]{60,50,40};//價值

    public static void main(String[] args)
    {
        int n=3;    //物品種類
        int v=100;    //揹包體積
        func(n, v);
        int s= m[n][v];      
        System.out.println("最大值為:" + s);
    }

    public static void func(int n, int v)
    {
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<=v; j++)
            {
                if(j>=v_arr[i])
                {
                    m[i + 1][j] = max(m[i][j], m[i][j - v_arr[i]] + t_arr[i]);
                }
                else
                {
                    m[i + 1][j] = m[i][j];
                }
            }
        }
    }

    public static int max(int a,int b) {
        int m;
        m = a;
        if (b > a)
            m = b;
        return m;
    }
}

  

第二種情況:

某人從外地販貨物回本省出售

有3種貨物:

A貨物,單個重量2KG,單個體積1立方,單個價值20塊

B貨物,單個重量1KG,單個體積6立方,單個價值60塊

C貨物,單個重量4KG,單個體積4立方,單個價值50塊

最大載重30KG,最大可以裝60立方,請用遞迴的演算法求出最優解

public class Main {

    public static int[][][] m = new int[4][61][31];
    public static int[] v_arr = new int[]{0,1,6,4};//物品體積
    public static int[] w_arr = new int[]{0,2,1,4};//重量
    public static int[] t_arr = new int[]{0,20,60,50};//價值

    public static void main(String[] args)
    {
        int n=3;    //物品種類
        int v=60;    //揹包體積
        int w=30;    //揹包載重
        func(n, v, w);       
        int s= m[n][v][w];
        System.out.println("最大值為:" + s);
    }

    public static void func(int n, int v, int w )
    {    //可選前3個物品,體積不超過60,重量不超過30

        int i=0,j=0;
        int x=0,y=0;
        int k=0,max=0;

        //假如都用第1個物品來填充,一個60*30的二維陣列,第1個物品體積1,重量2,價值20,從體積看能放60個,從重量看能放15個
        //60行,30列的陣列
        for(x=0;x<=v;x++)
        {
            for (y = 0; y <= w; y++)
            {
                if ((x / v_arr[1] > 0) && (y / w_arr[1] > 0))//x>=v_arr[1]&&y>=w_arr[1]
                {
                    m[1][x][y] = min(x / v_arr[1], y / w_arr[1]) * t_arr[1];//重量和體積都滿足的情況的個數,乘以價值等於m[1][x][y]取最大值
                }
                else
                {
                    m[1][x][y] = 0;
                }
            }
        }

        //因為有第2種物品,開始第二種物品來填充
        for(i=2;i<=n;i++)//從第i=2開始填充
        {
            //m[2][x][y]為加上第二種物品的60*30的二維陣列
            for (x = 0; x <= v; x++)
            {
                for (y = 0; y <= w; y++)
                {
                    max = m[i - 1][v][w];//原本這裡為這裡為m[i - 1][x][y],但是最大值一定為m[i - 1][v][w],下面能減少計算

                    //開始算第2個物品了,第2個物品體積6,重量1,價值60,從體積看能放10個,從重量看能放30個
                    if ((x >= v_arr[i]) && (y >= w_arr[i]))
                    {
                        for (k = 0; k <= min(x / v_arr[i], y / w_arr[i]); k++)
                        {
                            if ((m[i - 1][x - k * v_arr[i]][y - k * w_arr[i]] + k * t_arr[i]) > max)//找出符合的最大的
                            {
                                max = (m[i - 1][x - k * v_arr[i]][y - k * w_arr[i]] + k * t_arr[i]);
                                String str=String.format("物品%d:%d個,物品%d:%d個", i-1,min((x - k * v_arr[i])/v_arr[i-1], (y - k * w_arr[i])/w_arr[i-1]),i,k);
                                System.out.println(str);
                            }
                        }
                        m[i][x][y] = max;
                    }
                    else
                    {
                        m[i][x][y] = m[i - 1][x][y];
                    }
                }
            }
        }
    }

    public static int min(int a,int b) {
        int m;
        m = a;
        if (b < a)
            m = b;
        return m;
    }
}