非递归回溯法解决最小机器重量问题
问题描述:
设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。
设 W ij 是从供应商 j 处购得的部件 i 的重量,C ij 是其价格。
设计一个算法,给出总价不超过C的最小重量机器设计。
import java.util.Arrays;
public class Machine {
private int smallestWeight = 1000; //保存最小机器重量
private int currentWeight = 0;//当前选好的部件总重量
private int maxPrice = 8;//最大价格
private int sumPrice = 0;//最后求得的总价格
private int currentPrice = 0;//当前选好的部件总价格
private int weight[][] = { { 3, 2, 3 }, { 2, 1, 3 }, { 3, 4, 2 } }; // 第i个部件第j个供应商的重量
private int price[][] = { { 1, 2, 3 }, { 4, 4, 1 }, { 1, 1, 2 } }; // 第i个部件第j个供应商的宽度
private int supplier[]; // supplier[]元素个数表示部件总数, 每个元素表示遍历到第几个供应商
public void analyse() {
supplier = new int[weight.length]; // **************supplier[]元素个数表示部件总数,
// 每个元素表示遍历到第几个供应商
Arrays.fill(supplier, 0); // 初始化
int part = 0; // 第几号部件,相当于层数
while (supplier[0] < weight[0].length) { //深度遍历解空间树,直到最顶层节点被剪完枝
for (; part < supplier.length && supplier[part] < weight[0].length;) { // 深度优先搜索
if (currentWeight + weight[part][supplier[part]] > smallestWeight
|| price[part][supplier[part]] + currentPrice > maxPrice) {
// 加上当前部件重量之后 大于最优重量 或 超出最大价格
supplier[part]++; // 剪枝
} else { // 可以加上该供应商的部件
currentWeight += weight[part][supplier[part]];
currentPrice += price[part][supplier[part]];
part++;
}
}
if (part >= supplier.length) { // 如果到达底部
smallestWeight = currentWeight; // **************保存最优解
sumPrice = currentPrice;
part--; // 回溯
}
if (supplier[part] >= weight[0].length) { // 如果剪完枝
supplier[part] = 0;
part--; // 回到当前部件
}
currentWeight -= weight[part][supplier[part]];
currentPrice -= price[part][supplier[part]];
supplier[part]++; // 下一个供应商
}
if(smallestWeight != 1000)
System.out.println("最小重量是:" + smallestWeight + " 总价是:" + sumPrice);
else
System.out.println("该机器无法组装!");
}
}
public class MachineDome {
public static void main(String arg[]){
new Machine().analyse();
}
}