एक उच्च-आयामी जाली जैसे ग्राफ़ में सबसे बड़ा स्वतंत्र सेट खोजें


16

दिए गए सकारात्मक पूर्णांक के लिए n, लंबाई के सभी द्विआधारी तारों पर विचार करें 2n-1। किसी दिए गए स्ट्रिंग के लिए S, Lलंबाई की एक सरणी हो nजिसमें लंबाई के 1प्रत्येक विकल्प में s की संख्या की गिनती nहो S। उदाहरण के लिए, यदि n=3और S = 01010फिर L=[1,2,1]। हम Lगिनती के सरणी कहते हैं S

हम कहते हैं कि दो तार S1और S2एक ही लंबाई के मैच उनके संबंधित गिनती सरणियों अगर L1और L2है कि संपत्ति है L1[i] <= 2*L2[i]और L2[i] <= 2*L1[i]सभी के लिए i

कार्य

nशुरुआत में वृद्धि के लिए n=1, कार्य स्ट्रिंग्स के सबसे बड़े सेट के आकार का पता लगाना है, प्रत्येक की लंबाई, 2n-1ताकि कोई दो स्ट्रिंग्स का मिलान न हो।

आपका कोड प्रति मूल्य एक नंबर आउटपुट होना चाहिए n

स्कोर

आपका स्कोर उच्चतम nहै जिसके लिए किसी अन्य ने आपके किसी भी उत्तर के लिए उच्चतर सही उत्तर पोस्ट नहीं किया है। स्पष्ट रूप से यदि आपके पास सभी इष्टतम उत्तर हैं, तो आप उच्चतम nपद के लिए स्कोर प्राप्त करेंगे । हालांकि, भले ही आपका जवाब इष्टतम न हो, फिर भी आप स्कोर प्राप्त कर सकते हैं यदि कोई और इसे हरा नहीं सकता है।

उदाहरण उत्तर

क्योंकि n=1,2,3,4मुझे मिलता है 2,4,10,16

भाषाएं और पुस्तकालय

आप अपनी पसंद की किसी भी उपलब्ध भाषा और लाइब्रेरी का उपयोग कर सकते हैं। जहां संभव हो, अपने कोड को चलाने में सक्षम होना अच्छा होगा इसलिए कृपया अपने कोड को लिनक्स में चलाने / संकलित करने के लिए पूर्ण विवरण शामिल करें यदि संभव हो तो।

अग्रणी प्रविष्टियाँ

  • 5 गणितज्ञ मार्टिन मार्टिन द्वारा
  • सी ++ में रेटो कोराडी द्वारा 6 । मान हैं2, 4, 10, 16, 31, 47, 75, 111, 164, 232, 328, 445, 606, 814, 1086 । पहले 5 को इष्टतम माना जाता है।
  • 7 जावा में पीटर टेलर द्वारा । मान हैं 2, 4, 10, 16, 31, 47, 76, 111, 166, 235
  • 9 जावा में joriki द्वारा । मान हैं 2, 4, 10, 16, 31, 47, 76, 112, 168

3
मुझे लगता है कि जब असमानता हो तो असमानता को समझना अधिक स्वाभाविक है L1[i]/2 <= L2[i] <= 2*L1[i]
orlp

1
इसके अलावा, मिलान है नहीं एक तुल्यता संबंध। match(A, B)और (प्रतिलोम के लिए समान) का match(B, C)अर्थ नहीं है match(A, C)। उदाहरण: [१] और [२] मैच, [२] और [३] मैच, लेकिन [१] और [३] नहीं। इसी तरह, [१,३] और [३,१] मेल नहीं खाते, [३, १] और [२, ३] मेल नहीं खाते, लेकिन [१, ३] और [२, ३] मेल खाते हैं।
orlp

जवाबों:


7

2, 4, 10, 16, 31, 47, 76, 112, 168

प्रत्येक एन के लिए, यह जावा कोड संभावित गिनती सरणियों को निर्धारित करता है और फिर बढ़ते आकार के गैर-मिलान सेट को ढूंढता है, प्रत्येक आकार के लिए एक यादृच्छिक सेट से शुरू होता है और यादृच्छिक रूप से सबसे मजबूत वंश द्वारा इसे सुधारता है। प्रत्येक चरण में, सेट के तत्वों में से एक को बेतरतीब ढंग से समान रूप से चुना जाता है और एक और गिनती सरणी द्वारा प्रतिस्थापित किया जाता है बेतरतीब ढंग से समान रूप से उन लोगों के बीच चुना जाता है जो उपयोग में नहीं हैं। यदि यह मैचों की संख्या में वृद्धि नहीं करता है तो कदम स्वीकार किया जाता है। यह बाद वाला नुस्खा महत्वपूर्ण प्रतीत होता है; यदि वे मैचों की संख्या को कम करते हैं तो केवल कदमों को स्वीकार करना लगभग उतना प्रभावी नहीं है। माचिस की संख्या को छोड़ने वाले कदमों से खोज स्थान की खोज की जा सकती है, और अंततः कुछ मैचों में से बचने के लिए कुछ स्थान खुल सकता है। सुधार के बिना 2 ^ 24 चरणों के बाद, पिछले आकार एन के वर्तमान मूल्य के लिए आउटपुट है, और एन वेतन वृद्धि है।

N = 9 तक के 2, 4, 10, 16, 31, 47, 76, 112, 168परिणाम, पिछले परिणामों पर n = 8 के लिए एक और n = 9 के लिए दो से सुधार कर रहे हैं । N के उच्च मूल्यों के लिए, 2 ^ 24 चरणों की सीमा बढ़ानी पड़ सकती है।

मैंने सिम्युलेटेड एनेलिंग (ऊर्जा के रूप में मैचों की संख्या के साथ) की कोशिश की, लेकिन बिना सख्त सुधार के।

कोड

Question54354.java
साथ javac Question54354.java
चलाने के साथ संकलन के रूप में सहेजेंjava Question54354

import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class Question54354 {
    static class Array {
        int [] arr;

        public Array (int [] arr) {
            this.arr = arr;
        }

        public int hashCode () {
            return Arrays.hashCode (arr);
        }

        public boolean equals (Object o) {
            return Arrays.equals (((Array) o).arr,arr);
        }
    }

    static int [] indices;
    static int [] [] counts;
    static boolean [] used;

    static Random random = new Random (0);

    static boolean match (int [] c1,int [] c2) {
        for (int k = 0;k < c1.length;k++)
            if (c1 [k] > 2 * c2 [k] || c2 [k] > 2 * c1 [k])
                return false;
        return true;
    }

    static int matches (int i) {
        int result = 0;
        for (int j = 0;j < indices.length;j++)
            if (j != i && match (counts [indices [i]],counts [indices [j]]))
                result++;
        return result;
    }

    static void randomize (int i) {
        do
            indices [i] = random.nextInt (counts.length);
        while (used [indices [i]]);
    }

    public static void main (String [] args) {
        for (int n = 1,length = 1;;n++,length += 2) {
            int [] lookup = new int [1 << n];
            for (int string = 0;string < 1 << n;string++)
                for (int bit = 1;bit < 1 << n;bit <<= 1)
                    if ((string & bit) != 0)
                        lookup [string]++;
            Set<Array> arrays = new HashSet<Array> ();
            for (int string = 0;string < 1 << length;string++) {
                int [] count = new int [n];
                for (int i = 0;i < n;i++)
                    count [i] = lookup [(string >> i) & ((1 << n) - 1)];
                arrays.add (new Array (count));
            }
            counts = new int [arrays.size ()] [];
            int j = 0;
            for (Array array : arrays)
                counts [j++] = array.arr;
            used = new boolean [counts.length];

            int m;
            outer:
            for (m = 1;m <= counts.length;m++) {
                indices = new int [m];
                for (;;) {
                    Arrays.fill (used,false);
                    for (int i = 0;i < m;i++) {
                        randomize (i);
                        used [indices [i]] = true;
                    }
                    int matches = 0;
                    for (int i = 0;i < m;i++)
                        matches += matches (i);
                    matches /= 2;
                    int stagnation = 0;
                    while (matches != 0) {
                        int k = random.nextInt (m);
                        int oldMatches = matches (k);
                        int oldIndex = indices [k];
                        randomize (k);
                        int newMatches = matches (k);
                        if (newMatches <= oldMatches) {
                            if (newMatches < oldMatches) {
                                matches += newMatches - oldMatches;
                                stagnation = 0;
                            }
                            used [oldIndex] = false;
                            used [indices [k]] = true;
                        }
                        else
                            indices [k] = oldIndex;

                        if (++stagnation == 0x1000000)
                            break outer;
                    }
                    break;
                }
            }
            System.out.println (n + " : " + (m - 1));
        }
    }
}

1
एक बहुत अच्छा सुधार!

11

2, 4, 10, 16, 31, 47, 76, 111, 166, 235

टिप्पणियाँ

अगर हम एक ग्राफ पर विचार Gकोने के साथ 0करने के लिए nऔर किनारों दो नंबर जो मैच, तो शामिल होने टेन्सर बिजली G^n कोने है (x_0, ..., x_{n-1})कार्तीय बिजली बनाने {0, ..., n}^nऔर मिलान tuples के बीच किनारों। ब्याज का ग्राफ प्रेरित का उपसमूह हैG^n उन जो संभावित "गिनती सरण" के अनुरूप है।

तो पहला उपमा उन शीर्षकों को उत्पन्न करना है। भोले दृष्टिकोण 2^{2n-1}तार पर, या के आदेश पर enumerates 4^n। लेकिन अगर हम इसके बजाय गिनती सरणियों के पहले मतभेदों के सरणी को देखते हैं, तो हम पाते हैं कि केवल 3^nसंभावनाएं हैं, और पहले मतभेदों से हम संभव प्रारंभिक मूल्यों की सीमा को कम कर सकते हैं, जिसमें यह आवश्यकता होती है कि शून्य मतभेदों में कोई तत्व से कम 0या अधिक नहीं है से अधिक है n

हम तब अधिकतम स्वतंत्र सेट खोजना चाहते हैं। मैं एक प्रमेय और दो अनुमानों का उपयोग कर रहा हूं:

  • प्रमेय: रेखांकन के एक असंतुष्ट संघ का अधिकतम स्वतंत्र सेट उनके अधिकतम स्वतंत्र सेटों का संघ है। इसलिए यदि हम असंगत घटकों में एक ग्राफ को तोड़ते हैं तो हम समस्या को सरल बना सकते हैं।
  • अनुमानी: मान लें कि (n, n, ..., n)अधिकतम स्वतंत्र सेट में होगा। {m, m+1, ..., n}^nजहां mपर सबसे छोटा पूर्णांक होता है, वहां काफी बड़ा क्लिच होता है, जो मेल खाता है n; (n, n, ..., n)गारंटी है कि उस क्लिक के बाहर कोई मैच न हो।
  • हेयुरिस्टिक: सबसे कम डिग्री के शीर्ष का चयन करने का लालची दृष्टिकोण।

अपने कंप्यूटर पर इस पाता 111के लिए n=816 सेकंड, में 166के लिए n=98 के बारे में में मिनट, और 235के लिए n=102 के बारे में में घंटे।

कोड

के रूप में सहेजें PPCG54354.java, के रूप में संकलित करें javac PPCG54354.java, और के रूप में चलाएँ java PPCG54354

import java.util.*;

public class PPCG54354 {
    public static void main(String[] args) {
        for (int n = 1; n < 20; n++) {
            long start = System.nanoTime();

            Set<Vertex> constructive = new HashSet<Vertex>();
            for (int i = 0; i < (int)Math.pow(3, n-1); i++) {
                int min = 0, max = 1, diffs[] = new int[n-1];
                for (int j = i, k = 0; k < n-1; j /= 3, k++) {
                    int delta = (j % 3) - 1;
                    if (delta == -1) min++;
                    if (delta != 1) max++;
                    diffs[k] = delta;
                }

                for (; min <= max; min++) constructive.add(new Vertex(min, diffs));
            }

            // Heuristic: favour (n, n, ..., n)
            Vertex max = new Vertex(n, new int[n-1]);
            Iterator<Vertex> it = constructive.iterator();
            while (it.hasNext()) {
                Vertex v = it.next();
                if (v.matches(max) && !v.equals(max)) it.remove();
            }

            Set<Vertex> ind = independentSet(constructive, n);
            System.out.println(ind.size() + " after " + ((System.nanoTime() - start) / 1000000000L) + " secs");
        }
    }

    private static Set<Vertex> independentSet(Set<Vertex> vertices, int dim) {
        if (vertices.size() < 2) return vertices;

        for (int idx = 0; idx < dim; idx++) {
            Set<Set<Vertex>> p = connectedComponents(vertices, idx);
            if (p.size() > 1) {
                Set<Vertex> ind = new HashSet<Vertex>();
                for (Set<Vertex> part : connectedComponents(vertices, idx)) {
                    ind.addAll(independentSet(part, dim));
                }
                return ind;
            }
        }

        // Greedy
        int minMatches = Integer.MAX_VALUE;
        Vertex minV = null;
        for (Vertex v0 : vertices) {
            int numMatches = 0;
            for (Vertex vi : vertices) if (v0.matches(vi)) numMatches++;
            if (numMatches < minMatches) {
                minMatches = numMatches;
                minV = v0;
            }
        }

        Set<Vertex> nonmatch = new HashSet<Vertex>();
        for (Vertex vi : vertices) if (!minV.matches(vi)) nonmatch.add(vi);
        Set<Vertex> ind = independentSet(nonmatch, dim);
        ind.add(minV);
        return ind;
    }

    // Separates out a set of vertices which form connected components when projected into the idx axis.
    private static Set<Set<Vertex>> connectedComponents(Set<Vertex> vertices, final int idx) {
        List<Vertex> sorted = new ArrayList<Vertex>(vertices);
        Collections.sort(sorted, new Comparator<Vertex>() {
                public int compare(Vertex a, Vertex b) {
                    return a.x[idx] - b.x[idx];
                }
            });

        Set<Set<Vertex>> connectedComponents = new HashSet<Set<Vertex>>();
        Set<Vertex> current = new HashSet<Vertex>();
        int currentVal = 0;
        for (Vertex v : sorted) {
            if (!match(currentVal, v.x[idx]) && !current.isEmpty()) {
                connectedComponents.add(current);
                current = new HashSet<Vertex>();
            }

            current.add(v);
            currentVal = v.x[idx];
        }

        if (!current.isEmpty()) connectedComponents.add(current);
        return connectedComponents;
    }

    private static boolean match(int a, int b) {
        return a <= 2 * b && b <= 2 * a;
    }

    private static class Vertex {
        final int[] x;
        private final int h;

        Vertex(int[] x) {
            this.x = x.clone();

            int _h = 0;
            for (int xi : x) _h = _h * 37 + xi;
            h = _h;
        }

        Vertex(int x0, int[] diffs) {
            x = new int[diffs.length + 1];
            x[0] = x0;
            for (int i = 0; i < diffs.length; i++) x[i+1] = x[i] + diffs[i];

            int _h = 0;
            for (int xi : x) _h = _h * 37 + xi;
            h = _h;
        }

        public boolean matches(Vertex v) {
            if (v == this) return true;
            if (x.length != v.x.length) throw new IllegalArgumentException("v");
            for (int i = 0; i < x.length; i++) {
                if (!match(x[i], v.x[i])) return false;
            }
            return true;
        }

        @Override
        public int hashCode() {
            return h;
        }

        @Override
        public boolean equals(Object obj) {
            return (obj instanceof Vertex) && equals((Vertex)obj);
        }

        public boolean equals(Vertex v) {
            if (v == this) return true;
            if (x.length != v.x.length) return false;
            for (int i = 0; i < x.length; i++) {
                if (x[i] != v.x[i]) return false;
            }
            return true;
        }

        @Override
        public String toString() {
            if (x.length == 0) return "e";

            StringBuilder sb = new StringBuilder(x.length);
            for (int xi : x) sb.append(xi < 10 ? (char)('0' + xi) : (char)('A' + xi - 10));
            return sb.toString();
        }
    }
}

10

गणितज्ञ, n = 531 तार

मैंने सिर्फ लेम्बिक के उदाहरण उत्तरों को सत्यापित करने के लिए मैथमेटिका के अंतर्निहित इंसु का उपयोग करते हुए एक क्रूर बल समाधान लिखा है, लेकिन इसे n = 5ठीक से हल किया जा सकता है :

n = 5;
s = Tuples[{0, 1}, 2 n - 1];
l = Total /@ Partition[#, n, 1] & /@ s
g = Graph[l, 
  Cases[Join @@ Outer[UndirectedEdge, l, l, 1], 
   a_ <-> b_ /; 
    a != b && And @@ Thread[a <= 2 b] && And @@ Thread[b <= 2 a]]]
set = First@FindIndependentVertexSet[g]
Length@set

एक बोनस के रूप में, यह कोड एक ग्राफ के रूप में समस्या का एक दृश्य उत्पन्न करता है, जहां प्रत्येक किनारे दो मिलान तार इंगित करता है।

यहाँ के लिए ग्राफ है n = 3:

यहाँ छवि विवरण दर्ज करें


2
पहले मुझे लगा कि ग्राफ अच्छी तरह से सममित था, लेकिन फिर मैंने बाईं ओर थोड़ा ऑफसेट बिंदु देखा। अनसी नहीं कर सकते :(
orlp

3

C ++ (हेयुरिस्टिक): 2, 4, 10, 16, 31, 47, 75, 111, 164, 232, 328, 445, 606, 814, 1086

यह पीटर टेलर के परिणाम से थोड़ा पीछे है n=7, 9और 1 से 3 कम है , और 10। लाभ यह है कि यह बहुत तेज़ है, इसलिए मैं इसे उच्च मूल्यों के लिए चला सकता हूं n। और इसे बिना किसी फैंसी गणित के समझा जा सकता है। ;)

वर्तमान कोड को चलाने के लिए आयाम दिया गया है n=15। प्रत्येक में वृद्धि के लिए 4 के कारक द्वारा रन समय में लगभग वृद्धि होती है n। उदाहरण के लिए, यह 0.008 सेकंड के लिए n=7, 0.07 सेकंड के लिए n=9, 1.34 सेकंड के लिए n=11, 27 सेकंड के लिए n=13, और 9 मिनट के लिए है n=15

मेरे द्वारा उपयोग की जाने वाली दो प्रमुख टिप्पणियां हैं:

  • मूल्यों पर खुद को संचालित करने के बजाय, अनुमानी मतगणना सरणियों पर काम करता है। ऐसा करने के लिए, सभी अद्वितीय गिनती सरणियों की एक सूची पहले उत्पन्न होती है।
  • छोटे मानों के साथ गिनती सरणियों का उपयोग करना अधिक फायदेमंद है, क्योंकि वे समाधान स्थान के कम को खत्म करते हैं। यह प्रत्येक संख्या के आधार पर किया जाता है cकी सीमा को छोड़कर c / 2के लिए 2 * cअन्य मूल्यों से। के छोटे मानों के लिए c, यह श्रेणी छोटी है, जिसका अर्थ है कि इसका उपयोग करके कम मूल्यों को बाहर रखा गया है।

अद्वितीय काउंटिंग एरे उत्पन्न करें

मैं इस पर एक क्रूर बल गया, सभी मूल्यों के माध्यम से पुनरावृत्ति, उनमें से प्रत्येक के लिए गिनती सरणी का निर्माण, और परिणामी सूची को अद्वितीय बनाना। यह निश्चित रूप से अधिक कुशलता से किया जा सकता है, लेकिन यह उन मूल्यों के प्रकार के लिए पर्याप्त है जो हम संचालित कर रहे हैं।

यह छोटे मूल्यों के लिए अत्यंत त्वरित है। बड़े मूल्यों के लिए, ओवरहेड पर्याप्त हो जाता है। उदाहरण के लिए, n=15पूरे रनटाइम का लगभग 75% उपयोग करता है। यह निश्चित रूप से देखने का एक क्षेत्र होगा, जब इससे कहीं अधिक जाने की कोशिश की जा रही है n=15। यहां तक ​​कि सभी मूल्यों के लिए गिनती सरणियों की सूची बनाने के लिए भी स्मृति उपयोग समस्याग्रस्त होना शुरू हो जाएगा।

अद्वितीय गिनती सरणियों की संख्या के लिए मूल्यों की संख्या का लगभग 6% है n=15। यह सापेक्ष संख्या जितनी nबड़ी होती जाती है उतनी छोटी होती जाती है।

काउंटिंग एरे वैल्यूज़ का लालची चयन

एल्गोरिथ्म का मुख्य भाग एक साधारण लालची दृष्टिकोण का उपयोग करके उत्पन्न सूची से गिनती मान का चयन करता है।

इस सिद्धांत के आधार पर कि छोटे काउंट के साथ गिनती सरणियों का उपयोग करना फायदेमंद है, गिनती के सरणियों को उनके मायने के योग से हल किया जाता है।

फिर उन्हें क्रम में जांचा जाता है, और यदि पहले से उपयोग किए गए सभी मूल्यों के साथ संगत है, तो एक मूल्य चुना जाता है। इसलिए इसमें अद्वितीय गिनती सरणियों के माध्यम से एक एकल रैखिक पास शामिल है, जहां प्रत्येक उम्मीदवार की तुलना उन मूल्यों से की जाती है जो पहले चुने गए थे।

मेरे पास कुछ विचार हैं कि कैसे हेयुरिस्टिक को बेहतर बनाया जा सकता है। लेकिन यह एक उचित शुरुआती बिंदु की तरह लग रहा था, और परिणाम काफी अच्छे लग रहे थे।

कोड

यह अत्यधिक अनुकूलित नहीं है। मेरे पास कुछ बिंदु पर अधिक विस्तृत डेटा संरचना थी, लेकिन इसे परे सामान्य करने के लिए इसे और अधिक कार्य की आवश्यकता होगी n=8, और प्रदर्शन में अंतर बहुत महत्वपूर्ण नहीं था।

#include <cstdint>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <sstream>
#include <iostream>

typedef uint32_t Value;

class Counter {
public:
    static void setN(int n);

    Counter();
    Counter(Value val);

    bool operator==(const Counter& rhs) const;
    bool operator<(const Counter& rhs) const;

    bool collides(const Counter& other) const;

private:
    static const int FIELD_BITS = 4;
    static const uint64_t FIELD_MASK = 0x0f;

    static int m_n;
    static Value m_valMask;

    uint64_t fieldSum() const;

    uint64_t m_fields;
};

void Counter::setN(int n) {
    m_n = n;
    m_valMask = (static_cast<Value>(1) << n) - 1;
}

Counter::Counter()
  : m_fields(0) {
}

Counter::Counter(Value val) {
    m_fields = 0;
    for (int k = 0; k < m_n; ++k) {
        m_fields <<= FIELD_BITS;
        m_fields |= __builtin_popcount(val & m_valMask);
        val >>= 1;
    }
}

bool Counter::operator==(const Counter& rhs) const {
    return m_fields == rhs.m_fields;
}

bool Counter::operator<(const Counter& rhs) const {
    uint64_t lhsSum = fieldSum();
    uint64_t rhsSum = rhs.fieldSum();
    if (lhsSum < rhsSum) {
        return true;
    }
    if (lhsSum > rhsSum) {
        return false;
    }

    return m_fields < rhs.m_fields;
}

bool Counter::collides(const Counter& other) const {
    uint64_t fields1 = m_fields;
    uint64_t fields2 = other.m_fields;

    for (int k = 0; k < m_n; ++k) {
        uint64_t c1 = fields1 & FIELD_MASK;
        uint64_t c2 = fields2 & FIELD_MASK;

        if (c1 > 2 * c2 || c2 > 2 * c1) {
            return false;
        }

        fields1 >>= FIELD_BITS;
        fields2 >>= FIELD_BITS;
    }

    return true;
}

int Counter::m_n = 0;
Value Counter::m_valMask = 0;

uint64_t Counter::fieldSum() const {
    uint64_t fields = m_fields;
    uint64_t sum = 0;
    for (int k = 0; k < m_n; ++k) {
        sum += fields & FIELD_MASK;
        fields >>= FIELD_BITS;
    }

    return sum;
}

typedef std::vector<Counter> Counters;

int main(int argc, char* argv[]) {
    int n = 0;
    std::istringstream strm(argv[1]);
    strm >> n;

    Counter::setN(n);

    int nBit = 2 * n - 1;
    Value maxVal = static_cast<Value>(1) << nBit;

    Counters allCounters;

    for (Value val = 0; val < maxVal; ++val) {
        Counter counter(val);
        allCounters.push_back(counter);
    }

    std::sort(allCounters.begin(), allCounters.end());

    Counters::iterator uniqEnd =
        std::unique(allCounters.begin(), allCounters.end());
    allCounters.resize(std::distance(allCounters.begin(), uniqEnd));

    Counters solCounters;
    int nSol = 0;

    for (Value idx = 0; idx < allCounters.size(); ++idx) {
        const Counter& counter = allCounters[idx];

        bool valid = true;
        for (int iSol = 0; iSol < nSol; ++iSol) {
            if (solCounters[iSol].collides(counter)) {
                valid = false;
                break;
            }
        }

        if (valid) {
            solCounters.push_back(counter);
            ++nSol;
        }
    }

    std::cout << "result: " << nSol << std::endl;

    return 0;
}

मेरे पास समान कोड के आधार पर पुनरावर्ती समाधान थे जो अधिकतम खोजने के लिए गारंटी हैं। लेकिन इसमें n=4पहले ही थोड़ा समय लग गया । यह n=5कुछ धैर्य के साथ समाप्त हो सकता है । आपने इसे बनाने के लिए बेहतर बैकट्रैकिंग रणनीति का इस्तेमाल किया होगा n=7। क्या आपका उत्तराधिकारी था, या उसने संपूर्ण समाधान स्थान का पता लगाया था? मैं कुछ विचारों पर विचार कर रहा हूं कि इसे कैसे बेहतर बनाया जाए, या तो छँटाई के क्रम को ठीक से, या शायद विशुद्ध रूप से लालची न होने के द्वारा।
रेटो कोराडी

मेरी समझ यह है कि पीटर टेलर के जवाब में कोई पीछे नहीं है। यह विशुद्ध रूप से लालची है। मुख्य चाल यह है कि वह गिनती के सरणियों की संख्या को कम कर देता है 3^nऔर दो उत्तराधिकारियों का वर्णन करता है।

@Lembik मेरी टिप्पणी एक टिप्पणी के जवाब में थी जिसे हटा दिया गया था। मतगणना सरणियों की संख्या समान होनी चाहिए, क्योंकि मैं वास्तविक मूल्यों के आधार पर इसका निर्माण करता हूं, और इसे केवल अद्वितीय लोगों तक ही सीमित करता हूं। मैंने अल्गोरिद्म का बैकट्रैकिंग संस्करण अपडेट किया। भले ही यह एक उचित समय के भीतर समाप्त नहीं होता है, यह n=7जल्दी से 76 पाता है । लेकिन इसके लिए कोशिश करते हुए n=9, यह अभी भी 164 पर अटक गया था जब मैंने इसे 20 मिनट के बाद रोक दिया था। इसलिए साधारण बैकट्रैकिंग के सीमित रूप के साथ इसका विस्तार आमतौर पर आशाजनक नहीं लगता है।
रेटो कोराडी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.