Problem Description:
There are a total of n cargoes to be loaded on two ships with weights c1 and c2 respectively, where the weight of cargo i is Wi, and:
Request to determine if there is a reasonable loading scheme to load the cargo on both ships.
Take strategies:
(1) First fill the first ship as much as possible;
(2) Load the remaining containers on the second ship. Filling the first ship as full as possible is equivalent to choosing a subset of the total container in
which the sum of the container weights is the closest. It follows that the loading problem is equivalent to the following special 0-1 knapsack problem:
Bound function:
Define a CW to represent the weight of reaching the current node O. If CW>C1, it means that the subtree rooted at O cannot produce a feasible solution and avoid moving.
defect:
The right child of a feasible node is always feasible.
Algorithm improvements:
If the right subtree of the current node cannot contain a better solution than the current optimal solution, it does not move to the right subtree.
Let bestW be the current optimal solution, and Z be a node in the i-th layer of the solution space tree.
Improved bound function:
Let r be the weight of the remaining container, when CW+r<=bestW, there is no need to search the right subtree of Z.
Not much to say, go directly to the code:
package set; public class Loading { static int n;//Number of containers static int[] w;//Container weight array static int c;//The weight of the first ship static int cw;//Currently loaded weight static int bestw;//The weight of the current optimal load static int r;//The weight of the remaining container static int[] x;//The current solution, record the path from the root to the current node static int[] bestx;//Record the current optimal solution public static int MaxLoading(int[] ww,int cc) { //Initialize the data members, the array subscript starts from 1 n = ww.length - 1; w = ww; c = cc; cw = 0; bestw = 0; x = new int[n+1]; bestx = new int[n+1]; //Initialize r, that is, the remaining maximum weight for(int i =1;i<=n;i++) { r += w[i]; } //Calculate the optimal load backtrack(1); return bestw; } // backtracking algorithm public static void backtrack(int t) { if(t>n) {//reach the leaf node if(cw>bestw) { for(int i=1;i<=n;i++) { bestx[i] = x[i]; } bestw = cw; } return; } r -= w[t]; if(cw + w[t] <= c) {//Search the left subtree x[t] = 1; cw += w[t]; backtrack(t+1); cw -= w[t];//Backtrack } if(cw + r>bestw) { x[t] = 0;//Search the right subtree backtrack(t+1); } r += w[t];//Restore the scene } /* * If the right subtree of the current node cannot contain a better solution than the current optimal solution, do not move to the right subtree! Let bestw be the current optimal solution, and Z be a node in the i-th layer of the solution space tree is the weight of the remaining container; when cw+r<=bestw, there is no need to search the right subtree of Z: Current load capacity cw + weight of remaining containers r Current optimal load capacity bestw */ public static void main(String[] args) { // TODO Auto-generated method stub int[] ww = {0,20,30,60,40,40}; int c1 = 100; int c2 = 100; int n = ww.length - 1; MaxLoading(ww,c1); int weight2 = 0;//Save the possible weight of the second ship for(int i=1;i<=n;i++) { weight2 += ww[i]*(1-bestx[i]);//The value of bestx[i] can only be 0 or 1 } if(weight2>c2) { System.out.println("无解"); } else { System.out.println("The weight of the first ship loaded: " + bestw); System.out.println("The weight of the second ship's cargo: " + weight2); // Loading of the first ship for(int i = 1;i<=n;i++) { if(bestx[i] == 1) { System.out.println("The first" + i + "pieces of goods loaded into the first ship"); } } // Loading of the second ship for(int i = 1;i<=n;i++) { if(bestx[i] == 0) { System.out.println("The first" + i + "pieces of goods loaded into the second ship"); } } } } }
operation result: