Java 三胞胎的最佳合并

Java 三胞胎的最佳合并,java,algorithm,optimization,Java,Algorithm,Optimization,我试图为以下问题提出一个算法: 我有一个三元组的整数集合——让我们称这些整数为a、B、C。其中存储的值可能很大,因此通常不可能创建大小为a、B或C的数组。目标是最小化集合的大小。为此,我们提供了一个简单的规则,允许我们合并三元组: 对于两个三元组(A,B,C)和(A',B',C'),如果B==B'和C=C',其中|是按位或,则移除原始三元组并放置三元组(A | A',B,C)。类似的规则也适用于B和C 换句话说,如果两个三元组的两个值相等,则移除这两个三元组(按位或第三个值),并将结果放入集

我试图为以下问题提出一个算法:

我有一个三元组的整数集合——让我们称这些整数为a、B、C。其中存储的值可能很大,因此通常不可能创建大小为a、B或C的数组。目标是最小化集合的大小。为此,我们提供了一个简单的规则,允许我们合并三元组:

  • 对于两个三元组(A,B,C)和(A',B',C'),如果B==B'和C=C',其中|是按位或,则移除原始三元组并放置三元组(A | A',B,C)。类似的规则也适用于B和C
换句话说,如果两个三元组的两个值相等,则移除这两个三元组(按位或第三个值),并将结果放入集合

贪婪的方法在类似的情况下通常是误导性的,对于这个问题也是如此,但我找不到一个简单的反例来给出正确的解决方案。对于包含250个项目的列表,正确的解决方案为14,贪婪合并计算的平均大小约为30(从20到70不等)。随着列表大小的增加,次优开销变得更大

我也尝试过使用设置的位计数,但没有发现有意义的结果。这是一个显而易见的事实,如果记录是唯一的(可以安全地假设),那么设置的位计数总是会增加

下面是愚蠢的贪婪实现(这只是一个概念,请不要考虑代码样式):

公共类记录{
长A;
长B;
长C;
公共静态void main(字符串[]args){
列表数据=新的ArrayList();
//用一些数据填充它
布尔发现;
做{
发现=错误;
外部:
对于(int i=0;i

你知道如何解决这个问题吗?

我没有解决办法,但我有一些想法

代表

这个问题的一个有用的可视化表示是把三元组看成是三维空间的点。你有整数,所以记录将是网格的节点。并且当两个记录都是可连接的时,也只有当代表它们的节点位于同一轴上时。

反例

我找到了一个(最小的)贪心算法可能失败的例子。考虑下面的记录:

(1, 1, 1)   \ 
(2, 1, 1)   |     (3, 1, 1)  \
(1, 2, 1)   |==>  (3, 2, 1)  |==> (3, 3, 1)
(2, 2, 1)   |     (2, 2, 2)  /    (2, 2, 2)
(2, 2, 2)   /
但如果选择错误的方式,它可能会被困在三项记录上:

(1, 1, 1)   \ 
(2, 1, 1)   |     (3, 1, 1)
(1, 2, 1)   |==>  (1, 2, 1)
(2, 2, 1)   |     (2, 2, 3)
(2, 2, 2)   /
直觉 我觉得这个问题在某种程度上类似于在图中寻找最大匹配。大多数算法通过从任意次优解开始寻找最优解,并通过搜索增广路径使其在每次迭代中“更优”,这些路径具有以下特性:

  • 它们很容易找到(节点数的多项式时间)
  • 扩展路径和当前解决方案可以被精心设计成一个新的解决方案,它严格地优于当前解决方案
  • 如果没有找到增广路径,则当前解决方案是最优的

  • 我认为你的问题的最佳解决方案也可以本着同样的精神找到。

    这将是一个很长的答案,遗憾的是没有最佳解决方案(对不起).然而,这是一次认真的尝试,试图将贪婪问题解决方法应用于您的问题,因此原则上可能会有用。我没有实施讨论的最后一种方法,也许这种方法可以产生最佳解决方案--但我不能保证这一点

    0级:不是很贪婪 根据定义,贪婪算法具有一种启发式方法,用于以局部最优的方式选择下一步,即现在最优,希望达到全局最优,这可能总是可能的,也可能不是

    你的算法选择了任何一个mergable对,并将它们合并,然后继续。它不会评估这个合并意味着什么以及是否有更好的局部解决方案。因此,我根本不会称你的方法为贪婪。它只是一个解决方案,一种方法。我将它称为盲算法,以便我能简洁地引用它n我的答案。我还将使用一个稍微修改过的算法版本,它不是删除两个三元组并附加合并的三元组,而是只删除第二个三元组并用合并的三元组替换第一个三元组。结果三元组的顺序不同,因此最终结果可能也不同。让我运行这个修改过的算法ithm位于代表性数据集上,标记为使用
    *
    合并的三元组:

    0: 3 2 3   3 2 3   3 2 3
    1: 0 1 0*  0 1 2   0 1 2
    2: 1 2 0   1 2 0*  1 2 1
    3: 0 1 2*
    4: 1 2 1   1 2 1*
    5: 0 2 0   0 2 0   0 2 0
    
    Result: 4
    
    一级:贪婪 要使用贪婪算法,您需要以一种允许在多个选项可用时比较选项的方式制定合并决策。对我来说,合并决策的直观公式是:

    如果我合并这两个三胞胎,你会吗
    0: 3 2 3   3 2 3   3 2 3
    1: 0 1 0*  0 1 2   0 1 2
    2: 1 2 0   1 2 0*  1 2 1
    3: 0 1 2*
    4: 1 2 1   1 2 1*
    5: 0 2 0   0 2 0   0 2 0
    
    Result: 4
    
              mergables
    0: 3 2 3  (1,3)->2
    1: 0 1 0  (1,5)->1
    2: 1 2 0  (2,4)->2
    3: 0 1 2  (2,5)->2
    4: 1 2 1
    5: 0 2 0
    
              mergables
    0: 3 2 3  (2,3)->0
    1: 0 1 2  (2,4)->1
    2: 1 2 0
    3: 1 2 1
    4: 0 2 0
    
              mergables
    0: 3 2 3  (2,3)->0   3 2 3
    1: 0 1 2             0 1 2
    2: 1 2 0             1 2 1
    3: 1 2 1
    
    Result: 3
    
              mergables
    0: 3 2 3  (1,3)->(2,3)->0
    1: 0 1 0         (2,4)->1*
    2: 1 2 0  (1,5)->(2,4)->0
    3: 0 1 2  (2,4)->(1,3)->0
    4: 1 2 1         (1,4)->0
    5: 0 2 0  (2,5)->(1,3)->1*
                     (2,4)->1*