হাই-ডাইমেনশনাল ল্যাটিসের মতো গ্রাফের বৃহত্তম বৃহত্তম সেটটি সন্ধান করুন


16

প্রদত্ত ধনাত্মক পূর্ণসংখ্যার জন্য n, দৈর্ঘ্যের সমস্ত বাইনারি স্ট্রিং বিবেচনা করুন 2n-1। একটি প্রদত্ত STRING এর জন্য Sযাক Lদৈর্ঘ্যের একটি অ্যারের হতে nযার সংখ্যা গণনা রয়েছে 1দৈর্ঘ্য প্রতিটি সাবস্ট্রিং মধ্যে গুলি 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 মধ্যে Reto Koradi দ্বারা সি ++ । মান হয় 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 দ্বারা । মান হয় 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)( বিপরীতে একই)। উদাহরণ: [1] এবং [2] ম্যাচ, [2] এবং [3] ম্যাচ, তবে [1] এবং [3] মিলছে না। একইভাবে, [1,3] এবং [3,1] মিলছে না, [3, 1] এবং [2, 3] মিলছে না, তবে [1, 3] এবং [2, 3] মিলছে।
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 অনুপ্রাণিত হওয়া সাবগ্রাফ যা সম্ভাব্য "গণনা অ্যারে" এর সাথে সামঞ্জস্য করে।

সুতরাং প্রথম সাবটাস্কটি হ'ল vert শীর্ষটি তৈরি করা। নির্বাক দৃষ্টিভঙ্গি 2^{2n-1}স্ট্রিংগুলির উপর বা ক্রমের উপরে গণনা করে 4^n। তবে যদি আমরা পরিবর্তে গণনার অ্যারেগুলির প্রথম পার্থক্যের অ্যারে দেখি তবে আমরা দেখতে পাই যে কেবলমাত্র 3^nসম্ভাবনা রয়েছে এবং প্রথম পার্থক্য থেকে আমরা জিরোথ পার্থক্যের কোনও উপাদান কম 0বা এর চেয়ে কম নয় তা প্রয়োজনীয় করে সম্ভাব্য প্রাথমিক মানগুলির পরিসরটি কমিয়ে আনতে পারি or চেয়ে বড় n

তারপরে আমরা সর্বাধিক স্বতন্ত্র সেটটি খুঁজতে চাই। আমি একটি উপপাদ্য এবং দুটি উপাচার ব্যবহার করছি:

  • উপপাদ্য: গ্রাফগুলির একটি বিচ্ছিন্ন ইউনিয়নের সর্বাধিক স্বতন্ত্র সেট হ'ল তাদের সর্বোচ্চ স্বাধীন সেটগুলির মিল sets সুতরাং আমরা যদি কোনও গ্রাফকে সংযোগযুক্ত উপাদানগুলিতে ভেঙে ফেলি তবে আমরা সমস্যাটি সহজ করতে পারি।
  • হিউরিস্টিক: ধরে নিন যে (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
প্রথমে আমি ভেবেছিলাম গ্রাফটি সুন্দরভাবে প্রতিসাম্যপূর্ণ, তবে তারপরে আমি বামদিকে সামান্য অফসেট পয়েন্টটি দেখেছি।
অনুলিপি

3

সি ++ (হিউরিস্টিক): 2, 4, 10, 16, 31, 47, 75, 111, 164, 232, 328, 445, 606, 814, 1086

এই পিটার টেইলরের ফলাফলের পিছনে সামান্য হয় 1 থেকে 3 জন্য নিম্ন হচ্ছে n=7, 9এবং 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, এই ব্যাপ্তিটি আরও ছোট, যার অর্থ এটি ব্যবহার করে খুব কম মান বাদ পড়ে।

স্বতন্ত্র গণনা অ্যারে তৈরি করুন

আমি এইটির উপর দৃ force় শক্তি প্রয়োগ করেছি, সমস্ত মানগুলির মধ্যে পুনরাবৃত্তি করেছি, তাদের প্রত্যেকের জন্য গণনা অ্যারের উত্পন্ন করছি এবং ফলাফলটি পৃথক করে দেব। এটি অবশ্যই আরও দক্ষতার সাথে করা যেতে পারে তবে আমরা যে ধরণের মান নিয়ে কাজ করছি তার পক্ষে এটি যথেষ্ট ভাল।

এটি ছোট মানগুলির জন্য অত্যন্ত দ্রুত। বৃহত্তর মানগুলির জন্য, ওভারহেড যথেষ্ট পরিমাণে হয়ে যায়। উদাহরণস্বরূপ, এর জন্য n=15এটি পুরো রানটাইমের প্রায় 75% ব্যবহার করে। এর চেয়ে অনেক বেশি যাওয়ার চেষ্টা করার সময় অবশ্যই এটি দেখার ক্ষেত্র হবে n=15। এমনকি সমস্ত মানগুলির জন্য গণনা অ্যারেগুলির তালিকা তৈরির জন্য কেবল মেমরির ব্যবহার সমস্যাযুক্ত হতে শুরু করবে।

অনন্য গণনা অ্যারেগুলির জন্য মানগুলির সংখ্যার প্রায় 6% n=15। এই আপেক্ষিক গণনা বড় হওয়ার সাথে সাথে আরও ছোট হয় n

অ্যারে মান গণনা করার লোভী নির্বাচন

অ্যালগরিদমের মূল অংশটি একটি সাধারণ লোভী পদ্ধতির সাহায্যে উত্পন্ন তালিকা থেকে অ্যারে মান গণনা নির্বাচন করে।

তত্ত্বের উপর ভিত্তি করে যে ছোট সংখ্যা গণনা করে অ্যারে ব্যবহার করা উপকারী, গণনা অ্যারেগুলি তাদের গণনাগুলির যোগফল অনুসারে বাছাই করা হয়।

তারপরে সেগুলি যথাযথভাবে চেক করা হয় এবং পূর্ববর্তী ব্যবহৃত মানগুলির সাথে সামঞ্জস্যপূর্ণ হলে একটি মান নির্বাচন করা হয়। সুতরাং এটিতে অনন্য গণনা অ্যারেগুলির মধ্যে একটি একক রৈখিক পাস জড়িত থাকে, যেখানে প্রতিটি প্রার্থীকে পূর্বে নির্বাচিত মানগুলির সাথে তুলনা করা হয়।

হিউরিস্টিক কীভাবে সম্ভাব্য উন্নতি করতে পারে সে সম্পর্কে আমার কিছু ধারণা রয়েছে। তবে এটি একটি যুক্তিসঙ্গত সূচনা পয়েন্টের মতো মনে হয়েছিল এবং ফলাফলগুলি বেশ ভাল দেখাচ্ছে looked

কোড

এটি অত্যন্ত অনুকূল নয়। আমার এক পর্যায়ে আরও বিস্তৃত ডেটা কাঠামো ছিল, তবে এটিকে বাইরে সাধারণ করার জন্য আরও কাজ করা দরকার ছিল 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হ'ল তিনি গণনার অ্যারে সংখ্যা এবং তিনি যে দুটি বর্ণনাকে বর্ণনা করেছেন তা হ্রাস করে ।

@ লেম্বিক আমার মন্তব্য মুছে ফেলা একটি মন্তব্যের প্রতিক্রিয়াতে ছিল। গণনার অ্যারেগুলির সংখ্যা একই হওয়া উচিত, যেহেতু আমি এটি বাস্তব মানের উপর ভিত্তি করে তৈরি করি এবং এটি কেবল অনন্যকেই হ্রাস করি। আমি অ্যালগরিদমের একটি ব্যাকট্র্যাকিং সংস্করণ আপডেট করেছি। যদিও এটি একটি যুক্তিসঙ্গত সময়ের মধ্যে শেষ হয় না, এটি n=7দ্রুত 76 এর সন্ধান করে । তবে এটির জন্য চেষ্টা করে n=9, আমি যখন 20 মিনিটের পরে এটি থামিয়েছিলাম তখন এটি 164 এ আটকে ছিল। সুতরাং সাধারণ ব্যাকট্র্যাকিংয়ের সীমিত আকারের সাথে এটি প্রসারিত করা সাধারণত আশাব্যঞ্জক বলে মনে হয় না।
রেটো কোরাদি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.