Java组合优化

时间:2015-11-13 20:11:16

标签: java knapsack-problem

我有一个组合优化问题。

我有X个出价,包含价格和n行。价格是这n行的总价。 n可以在1到12之间。所有行都附有一个数字(1-12)。这意味着总共有12个不同的行。出价永远不会有两次相同的行。我可以接受出价或拒绝出价。不可能以某种方式将出价分成两个(或更多)。

现在我有一个长度为12位的Bit数组,告诉我每一行是否需要该行。

我想要的是为我需要的行计算最便宜的可能分配。头疼我目前无法解决这个问题。也许你们其中一个人可以帮我一点。

这是我简单的Bid类:

public class Bid {
    private int price;
    private int[] rows; // e.g. rows[0] = 3 means this bid contains row 3
    private int connectionID;

    public Bid(int price, int[] rows, int connectionID) {
        super();
        this.price = price;
        this.rows = rows;
        this.connectionID = connectionID;
    }

    public int getPrice() {
        return price;
    }

    public int[] getRows() {
        return rows;
    }

    public int getConnectionID() {
        return connectionID;
    }   
}

非常感谢!

Ps.:ConnectionID帮助我识别出价。

1 个答案:

答案 0 :(得分:1)

有一种非常明显的方法:尝试每个子集。当你有30个项目因此有2个 30 子集时,这并不是很好,但如果你不介意等一下,那就没关系了。这不是需要几个月的事情。

但我们可以做得更好,至少平均而言。

技术#1,从搜索空间中修剪无用的树木。如果你将搜索组织成一个隐式二元树,它为每个项目选择“我是否接受这个”,那么在你一直到底之前,你可以决定的子树是没有意义的。最简单的就是获得目前为止暂时选择的所有项目的权重总和,如果这比你迄今为止找到的最便宜的解决方案更重要,那么以后它就不会改进(假设你没有负价格,你没有,因为如果有任何负价格,那么你只需要确保所有这些,然后不要将它们包括在这个搜索中)。仅这一点可能已经产生了很大的不同。

技术#2,避免死路一条。如果只剩下1个出价,但是你还没有包含某一行(所有其他的,如果有的话,暂时决定不包括该行的出价),则没有什么可以决定的,你必须接受。这当然可以迫使成本高于最佳成本,参见#1。

技术#3,使用可接受的启发式来修剪更多。例如,一个微不足道的:说某些行尚未涵盖。显然,为了产生解决方案,它必须被覆盖,因此在决定是否可以修剪该分支之前,可以将最便宜的方式添加到运行总计中。您不能只为所有未覆盖的行添加所有最低成本的总和,因为相同的出价可能涵盖其中的几个,但如果您采用最大值而不是总和,它将起作用。这里有更好的技巧,但这个很简单。