【问题标题】:Find unqiue sets of size r from a set of n elements with only 1 size subsets in common从只有 1 个大小的公共子集的 n 个元素的集合中找到大小为 r 的唯一集合
【发布时间】:2015-03-12 10:45:31
【问题描述】:

从 n 个元素中找到大小为 r 的唯一集合,使得大小大于 1 的子集在同一顺序中不常见。其中 r 小于 n。

对于 n=10 和 r=5,我能够找到 n 个唯一集合,它们只有大小为 1 的子集。即{1,3} 仅在该顺序的第一组中。

1   3   6   0   5
2   4   7   1   6
3   5   8   2   7
4   6   9   3   8
5   7   0   4   9
6   8   1   5   0
7   9   2   6   1
8   0   3   7   2
9   1   4   8   3
0   2   5   9   4

另一种解决方案

1   4   9   6   5
2   5   0   7   6
3   6   1   8   7
4   7   2   9   8
5   8   3   0   9
6   9   4   1   0
7   0   5   2   1
8   1   6   3   2
9   2   7   4   3
0   3   8   5   4

在一个解中似乎只有 n 个这样的集合是可能的。 如何在数学上证明这一点?

存在多少这样的解决方案,找到所有解决方案的算法是什么?

这个算法和证明是否可以扩展为包含 2 个(或 p,如果 p 小于 r)的共同子集。

这是一个已知问题并且可以通过编程方式解决吗?

我试图搜索 http://en.wikipedia.org/wiki/Fano_plane 似乎相关,但我不确定。

【问题讨论】:

  • 您似乎有一些不标准的术语。您的第一个示例包括1 3 6 0 50 2 5 9 4。子集 {0,5} 对两者都是通用的,并且顺序相同。请说出这个例子有什么属性。
  • 为错误道歉。我的意思是相同的顺序和相邻的。
  • 我不知道如何正确表达这一点。 0 2 5 9 4 确实有最小的 {0,5} 但中间有 2 个。只有一种情况是 {0,5} 以该顺序出现,中间没有任何其他元素。
  • 我们在一组 n 中有 2^{n} 个唯一子集(未排序)。但订购和尺寸,我不知道。算法我觉得很简单。
  • 法诺飞机是一条红鲱鱼。它是一个投影平面,如果您真的指的是子集而不是(连续的)子词,那么这些就是您想要的示例。相反,您需要类似 de Bruijn 序列的片段。它们的数量非常庞大。

标签: algorithm math set


【解决方案1】:

首先:我从您的示例和 cmets 中了解到,您的意思不是集合(无序),而是列表(有序)。

解决方案中并不总是有n 大小为r 的列表。 例如。 n = 3, r = 2

1  2
1  3
2  1
2  3
3  1
3  2

这是n⋅(n-1) = 3⋅2 = 6 大小为r 的列表的解决方案。

总共有精确的n⋅(n-1) 有序元素对。每个r 元素列表都包含r-1(重叠)对,因此r 元素的不同列表的理论最大值为n⋅(n-1)/(r-1)

r 元素列表的最大数量(short max-solution)的解决方案数量以n⋅(n-1)/(r-1) over mbinomial coefficent)为界,其中m 是最大解决方案中的列表数量.

在示例中,您看到有一个使用所有 6 个可能列表的最大解决方案,因此只有一个最大解决方案。
该示例还表明可以达到理论界限。

如果您对nr 使用更大的数字,则可能无法达到此限制。

查找所有的算法是使用回溯的枚举算法。只需列出所有可能的对并构建列表。如果您只对一个最大解感兴趣,那么可能存在更智能的算法。

【讨论】:

    【解决方案2】:

    显然,您的两个解决方案都违反了问题条件,第一个解决方案在第一行和第六行重复了 1 和 5 的序列,第二个解决方案在第二和第九行重复了 2 和 7 的序列,但是还是很有趣的。

    我创建了这段代码来实现您正在寻找的算法,我希望这不会浪费我的时间。 这足以证明问题可以通过编程方式解决。

    该算法包含三个重要的方法。

    order_accepted(ArrayList reslist, int c)

    搜索我们目前得到的列表,并在之前生成的列表中的列表(我们现在正在构建的)的任何元素之后发生 c 时返回 false。

    buildlist(ArrayList reslist, int siz_r, int[] arr)

    在不违反我们的条件的情况下建立一个列表,当然是使用前面的方法来检查。

    lists_start_with(int c, int siz_r, int[] arr)

    我们使用它来避免丢失以相同数字开头的列表,我们应该这样做,否则我们将得到不超过一个以任何元素开头的列表(如果存在的话),我们不能得到两个。

    build_solution(int[] arr, int siz_r)

    您需要此函数为每个输入数字调用先前的方法,以获取所有列表以它开头并将它们添加到解决方案中。

    要获得解决方案,请在 main 方法中设置输入数组 a 和大小 r,如:

    ag.build_solution(new int[]{1,2,3,....},r=..);
    

    解决方案:

    a={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}, r=17
    
    1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17    
    14  13  12  11  10  9   8   7   6   5    4    3    2    1    18   19   20  
    
    
     a={1,2,3,4,5}, r=4
    
     1    2    3    4    
     3    2    1    5    
      
     a={1,2,3,4,5,6,7,8,9}, r=4
    
     1    2    3    4    
     1    5    6    7    
     2    1    8    9    
     2    7    6    5    
     3    5    8    1    
     3    6    9    2    
     4    5    9    3    
     4    7    8    2    
     7    9    4    1 
    
    
     a={1,2,3,4,5,6,7,8,9}, r=3
    
     1    2    3    
     1    4    5    
     1    6    7    
     1    8    9    
     2    4    1    
     2    5    6    
     2    7    8    
     3    2    9    
     3    4    6    
     3    5    1    
     3    8    7    
     4    7    2    
     4    8    3    
     5    4    9    
     5    7    3    
     5    8    2    
     6    8    1    
     6    9    2    
     7    6    4     
     7    9    1    
     8    6    5     
     9    6    3    
     9    7    5    
     9    8    4 
    
    
     a={1,2,3,4,5,6,7,8,9}, r=6
    
     1    2    3    4    5    6    
     3    2    1    7    8    9    
     5    4    9    8    7    1   
    
     
    

    代码:

    类算法

    import java.util.ArrayList;
        import java.util.Iterator;
        import java.util.List;
        
        public class Alg {
            public static List<Object> solut = new ArrayList();
        
            @SuppressWarnings("rawtypes")
            public boolean order_accepted(ArrayList reslist, int c) {
                boolean result = true;
                if ((solut != null) && (solut.size() > 0)) {
                    Iterator iter = solut.iterator();
                    // for every list in this solution
                    while (iter.hasNext()) {
                        ArrayList temp = (ArrayList) iter.next();
                        if (temp != null && temp.size() > 0)
                            // for every element in our current list
                            for (int el = 0; el < reslist.size(); el++)
                            // for every element in this list of our solution
                                for (int j = 0; j < temp.size(); j++)
                                if (temp.get(j).equals(reslist.get(el))) {
                        // start looking for c in this list of our
                                        // solution
                                    for (int k = j; k < temp.size(); k++) {
                                if (temp.get(k).equals(c)) // if you find c
                                    // then it
                        // is after; so will not
                                                // be after any more;
                                                // drop c.
                                                return false;
        
                                        }
                                        break;
                                    }
        
                    }
                }
                return result;
            }
        
            public boolean is_in_list(int c, ArrayList lst) {
                boolean res = false;
                if (lst != null)
                    for (int i = 0; i < lst.size(); i++)
                        if ((Integer) lst.get(i) == c) {
                            res = true;
                            break;
                        }
        
                return res;
            }
        
            public ArrayList copylist(ArrayList lst) {
                ArrayList res = null;
                if (lst != null) {
                    res = new ArrayList();
                    for (int i = 0; i < lst.size(); i++) {
                        res.add(lst.get(i));
                    }
                }
                return res;
            }
        
        // we call this method after we set the first element of the list and
        // (recursively),
        // to get the next (r-1) elements from the input array (arr).
            @SuppressWarnings("unchecked")
        public boolean buildlist(ArrayList reslist, int siz_r, int[] arr) {
        boolean full = false;// this variable determine whether we added an
                    // element to this reslist or no available
                                        // element found
        
                if (reslist.size() < siz_r) {
                    for (int i = 0; i < arr.length; i++) {
        
                        // if arr[i] is not in the current list and,
            // its order (after) every element is accepted (never happened
                        // in the solution).
                        if (!is_in_list(arr[i], reslist)
                                && order_accepted(reslist, arr[i])) {
        
                            
                            reslist.add(arr[i]);
                            if (reslist.size() == siz_r)// list is full
                            {
                                full = true;
                                break;
                            } 
                            else 
                            {
                              
                                //if fill with others is possible
                                ArrayList tmp=copylist(reslist);
                                if(buildlist(tmp,siz_r,arr))
                                {
                                    return buildlist(reslist,siz_r,arr);
                                }
                                
                         //else remove this element
                         //and continue searching for others.
                                else
                                {
                                    reslist.remove(reslist.size()-1);
                                }
                            }
        
                            
                        }// endif
                    }// endfor
                    return full;
                } else
                    return true;
            }
        
            public void listes_start_with(int c, int siz_r, int[] arr) {
     // Don't start with other numbers when you still have other listes start
                // withe the same number, Example:
                // arr{1,2,3,4,5} r=3 => (1) 2 3; (1) 4 5; 2 4 1; ...
        // Note that only sub set of size One could be repeated in the same
                // order (relatively); ({12}3; {12}4 are wrong listes).
        
     boolean possible = true;// the possibility of finding other listes start
                            // with c by the result of buildlist method.
                while (possible) {
                    ArrayList ls = new ArrayList();
                    ls.add(c);
        
                    if (c == 2) {
                        int x = 0;
                        x += 1;
                    }
                    if (buildlist(ls, siz_r, arr))
                        solut.add(ls);
                    else
                        possible = false;
                }
            }
        
            public void build_solution(int[] arr, int siz_r) {
                for (int i = 0; i < arr.length; i++) {
                    listes_start_with(arr[i], siz_r, arr);
        
                }
            }
        
            @SuppressWarnings("rawtypes")
            public void showsolution() {
                for (int i = 0; i < solut.size(); i++) {
                    ArrayList temp = (ArrayList) solut.get(i);
                    if (temp != null && temp.size() > 0) {
                        for (int j = 0; j < temp.size(); j++) {
                            System.out.print(temp.get(j) + "    ");
                        }
                    }
                    System.out.println("");
                }
        
            }
    
            }
    

    主类

    public class Mclass {
    public static void main(String args[])
    {
        Alg ag=new Alg();
        ag.build_solution(new int[]{1,2,3,4,5,6,7,8,9},3);
        ag.showsolution();
        }
    }
    

    扩展算法以包含解决方案中的所有常见子集,我认为最好为此创建一个单独的子集。

    我无法从数学上证明解决方案中可能的列表数量。 甚至是解决方案的总数,因为我只知道(在此算法中)当您对输入数组进行不同排序时,您会得到不同的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-09
      • 1970-01-01
      • 1970-01-01
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      • 2013-03-27
      相关资源
      最近更新 更多