Tối ưu hóa việc sắp xếp, sử dụng đảo ngược vector Sub-vector


23

Đây là một thách thức trong đó mục tiêu là sắp xếp một vectơ theo thứ tự tăng dần bằng cách sử dụng các đảo ngược ít nhất. Thuật toán của bạn chỉ có thể sắp xếp vectơ bằng cách sử dụng "đảo ngược vectơ phụ" 1 , nhưng nó có thể sử dụng các phép toán khác cho các phép toán số học, các vòng lặp, kiểm tra xem nó có được sắp xếp không, v.v. Số lượng vectơ phụ của thuật toán của bạn thực hiện là điểm của nó.


1 "Đảo ngược vector phụ":

  • Chọn một phạm vi số trong vectơ và đảo ngược các phần tử trong phạm vi đó.

Để đưa ra một ví dụ đơn giản, nếu bạn bắt đầu với vectơ {4,3,2,1} , thì bạn có thể sắp xếp nó theo nhiều cách khác nhau:

  1. Đảo ngược toàn bộ vector. Đây rõ ràng là cách tiếp cận ngắn nhất vì nó chỉ yêu cầu một lần đảo ngược:{4,3,2,1} -> {1,2,3,4}
  2. Bạn có thể thực hiện một phiên bản sắp xếp bong bóng, yêu cầu 6 lần đảo ngược: {4,3,2,1} -> {3,4,2,1} -> {3,2,4,1} -> {2,3,4,1} -> {2,3,1,4} -> {2,1,3,4} -> {1,2,3,4}
  3. Bạn có thể bắt đầu với 3 yếu tố đầu tiên, sau đó là ba yếu tố cuối cùng và cuối cùng là hai yếu tố đầu tiên và hai yếu tố cuối cùng, yêu cầu 4 lần hoán đổi: {4,3,2,1} -> {2,3,4,1} -> {2,1,4,3} -> {1,2,4,3} -> {1,2,3,4}
  4. ... và cứ thế. Có vô số tùy chọn có sẵn (bạn có thể lặp lại bất kỳ thao tác nào nếu muốn).

Quy tắc và yêu cầu:

  • Mã của bạn phải hoàn thành trong vòng chưa đầy một phút cho danh sách có 100 số. Bạn có thể thời gian này, nhưng xin vui lòng chơi công bằng 2 .

  • Bạn phải lưu trữ các chỉ số bắt đầu và kết thúc của tất cả các giao dịch hoán đổi bạn thực hiện, để giải pháp có thể được xác minh. (Tôi sẽ giải thích điều này có nghĩa là gì bên dưới).

  • Mã phải có tính xác định.

  • Bạn có thể lấy đầu vào trên bất kỳ định dạng nào bạn muốn: Vectơ số, danh sách liên kết, mảng có độ dài ... bất cứ điều gì bạn thích.

  • Bạn có thể làm bất cứ điều gì bạn thích trên một bản sao của vectơ. Điều đó bao gồm cố gắng đảo ngược khác nhau và kiểm tra đó là hiệu quả nhất. Brute-buộc là hoàn toàn tốt, nhưng tuân theo giới hạn thời gian.

  • Điểm số là tổng số lần lật cho 5 vectơ kiểm tra. Tie-breaker sẽ đóng dấu ngày.


Thí dụ:

4 1 23 21 49 2 7 9 2 | Vectơ / danh sách ban đầu
4 1 2 9 7 2 49 21 23 | (2, 8) (lật các yếu tố giữa các chỉ số 2 và 8)
4 1 2 2 7 9 49 21 23 | (3, 5)
4 1 2 2 7 9 23 21 49 | (6, 8)
4 1 2 2 7 9 21 23 49 | (6, 7)
 2 2 1 4 7 9 21 23 49 | (0, 3)
 1 2 2 4 7 9 21 23 49 | (0, 2)

Điểm sẽ là 6, vì bạn đã thực hiện 6 lần đảo chiều. Bạn phải lưu trữ (không in) các chỉ mục được liệt kê ở phía bên phải trên một định dạng phù hợp có thể dễ dàng in / xuất ra cho mục đích xác minh.

Các vectơ kiểm tra:

133, 319, 80, 70, 194, 333, 65, 21, 345, 142, 82, 491, 92, 167, 281, 386, 48, 101, 394, 130, 111, 139, 214, 337, 180, 24, 443, 35, 376, 13, 166, 59, 452, 429, 406, 256, 133, 435, 446, 304, 350, 364, 447, 471, 236, 177, 317, 342, 294, 146, 280, 32, 135, 399, 78, 251, 467, 305, 366, 309, 162, 473, 27, 67, 305, 497, 112, 399, 103, 178, 386, 343, 33, 134, 480, 147, 466, 244, 370, 140, 227, 292, 28, 357, 156, 367, 157, 60, 214, 280, 153, 445, 301, 108, 77, 404, 496, 3, 226, 37

468, 494, 294, 42, 19, 23, 201, 47, 165, 118, 414, 371, 163, 430, 295, 333, 147, 336, 403, 490, 370, 128, 261, 91, 173, 339, 40, 54, 331, 236, 255, 33, 237, 272, 193, 91, 232, 452, 79, 435, 160, 328, 47, 179, 162, 239, 315, 73, 160, 266, 83, 451, 317, 255, 491, 70, 18, 275, 339, 298, 117, 145, 17, 178, 232, 59, 109, 271, 301, 437, 63, 103, 130, 15, 265, 281, 365, 444, 180, 257, 99, 248, 378, 158, 210, 466, 404, 263, 29, 117, 417, 357, 44, 495, 303, 428, 146, 215, 164, 99

132, 167, 361, 145, 36, 56, 343, 330, 14, 412, 345, 263, 306, 462, 101, 453, 364, 389, 432, 32, 200, 76, 268, 291, 35, 13, 448, 188, 11, 235, 184, 439, 175, 159, 360, 46, 193, 440, 334, 128, 346, 192, 263, 466, 175, 407, 340, 393, 231, 472, 122, 254, 451, 485, 257, 67, 200, 135, 132, 421, 205, 398, 251, 286, 292, 488, 480, 56, 284, 484, 157, 264, 459, 6, 289, 311, 116, 138, 92, 21, 307, 172, 352, 199, 55, 38, 427, 214, 233, 404, 330, 105, 223, 495, 334, 169, 168, 444, 268, 248

367, 334, 296, 59, 18, 193, 118, 10, 276, 180, 242, 115, 233, 40, 225, 244, 147, 439, 297, 115, 354, 248, 89, 423, 47, 458, 64, 33, 463, 142, 5, 13, 89, 282, 186, 12, 70, 289, 385, 289, 274, 136, 39, 424, 174, 186, 489, 73, 296, 39, 445, 308, 451, 384, 451, 446, 282, 419, 479, 220, 35, 419, 161, 14, 42, 321, 202, 30, 32, 162, 444, 215, 218, 102, 140, 473, 500, 480, 402, 1, 1, 79, 50, 54, 111, 189, 147, 352, 61, 460, 196, 77, 315, 304, 385, 275, 65, 145, 434, 39

311, 202, 126, 494, 321, 330, 290, 28, 400, 84, 6, 160, 432, 308, 469, 459, 80, 48, 292, 229, 191, 240, 491, 231, 286, 413, 170, 486, 59, 54, 36, 334, 135, 39, 393, 201, 127, 95, 456, 497, 429, 139, 81, 293, 359, 477, 404, 129, 129, 297, 298, 495, 424, 446, 57, 296, 10, 269, 350, 337, 39, 386, 142, 327, 22, 352, 421, 32, 171, 452, 2, 484, 337, 359, 444, 246, 174, 23, 115, 102, 427, 439, 71, 478, 89, 225, 7, 118, 453, 350, 109, 277, 338, 474, 405, 380, 256, 228, 277, 3

Tôi khá chắc chắn rằng việc tìm kiếm một giải pháp tối ưu là NP-hard (vì phân loại bánh kếp thông thường là).

2 Có, những người có máy tính rất nhanh có thể có lợi ích, do giới hạn thời gian là một phút. Sau nhiều cuộc thảo luận, tôi đã nhận ra rằng tốt nhất là nếu mọi người tự chấm điểm riêng, đó không phải là một thử thách mã nhanh nhất.



1
Giải pháp tối ưu tối đa phải tương đương với sắp xếp chèn theo số lần đảo ngược, mỗi lần đảo ngược có thể đặt một số duy nhất.
fnɛtɪk

3
Đây không phải là lật bánh kếp (chỉ có thể lật từ một vị trí cho đến khi kết thúc). Lựa chọn sắp xếp là O (n) và sử dụng hoán đổi n-1. Có những trường hợp xấu nhất trong đó hoán đổi n-1 là cần thiết. Lựa chọn sắp xếp là tối ưu tiệm cận.
orlp

1. Đầu vào có phải là danh sách / vectơ số nguyên không? 2. Điều gì nên là đầu ra của chương trình? 3. Chương trình có thể sắp xếp vectơ hoặc các phần của nó, nhiều lần, có thể sử dụng các phương thức khác nhau (chẳng hạn như quicksort), để xác định cách tối ưu hóa các hoạt động, miễn là nó thực hiện sắp xếp đảo ngược vectơ phụ của đầu vào vector (theo yêu cầu) ở cuối?
aditsu

1
@orlp Bạn có thể chứng minh rằng có những trường hợp xấu nhất với n-1flips không? Tôi chỉ có thể chứng minh giới hạn dưới khoảng 50.
user202729

Câu trả lời:


6

Java, thuật toán di truyền ish, 80 + 81 + 79 + 78 + 80 = 398 (trước đây là 418 )

Sau khi thử một loạt các ý tưởng khác nhau và chủ yếu là thất bại, tôi đã giải quyết thuật toán này: bắt đầu với mảng đầu vào, thử tất cả các đảo ngược có thể và giữ một số kết quả nhất định với số lần chạy nhỏ nhất, sau đó làm tương tự cho các kết quả đó, cho đến khi chúng tôi nhận được một mảng được sắp xếp.

Bằng cách "chạy", tôi có nghĩa là các tập hợp con tối đa xuất hiện chính xác hoặc đảo ngược trong mảng được sắp xếp. Về cơ bản chúng là các tập hợp con được sắp xếp tối đa, nhưng trong trường hợp các phần tử lặp lại, số phần tử ở giữa phải khớp. Ví dụ như nếu mảng được sắp xếp được 2, 2, 3, 3, 4, 4thì 4, 3, 3, 2là một hoạt động nhưng 2, 2, 3, 4không phải là (và không phải là 2, 3, 2).

Trong phiên bản này, tôi đã tối ưu hóa thuật toán để chỉ đảo ngược tại các ranh giới chạy và chỉ khi một lần chạy đảo ngược có thể được nối với một lần chạy mới liền kề. Ngoài ra, các bước chạy được điều chỉnh và nối vào mỗi bước, để tránh tính toán lại chúng từ mảng đã sửa đổi. Điều này cho phép tôi tăng "kích thước dân số" từ 30 lên khoảng 3000 và chạy nhiều mô phỏng ở các kích cỡ khác nhau.

import java.io.*;
import java.util.*;

public class SubReversal {
    static int n;
    static int[] a;
    static int[] srt;
    static List<int[]> rev;
    static Map<Integer, Integer> idx;
    static Map<Integer, Integer> count;

    static final int NB = 2000;
    static State[] best = new State[NB + 1];
    static int ns;

    static class Run {
        int start;
        int end;
        int dir;
        int nstart = 1;
        int nend = 1;

        Run(final int start) {
            this.start = start;
        }

        Run(final Run r) {
            start = r.start;
            end = r.end;
            dir = r.dir;
            nstart = r.nstart;
            nend = r.nend;
        }

        Run copy() {
            return new Run(this);
        }

        Run reverse() {
            int t = start;
            start = end;
            end = t;
            t = nstart;
            nstart = nend;
            nend = t;
            dir = -dir;
            return this;
        }

        boolean canJoin(final Run r) {
            if (dir * r.dir == -1) {
                return false;
            }
            final int t = idx.get(a[r.start]) - idx.get(a[end]);
            if (Math.abs(t) > 1) {
                return false;
            }
            if (t != 0 && dir + r.dir != 0 && t != dir && t != r.dir) {
                return false;
            }
            if (t == 0) {
                if (dir * r.dir == 0) {
                    return true;
                }
                return nend + r.nstart == count.get(a[end]);
            }
            return (dir == 0 || nend == count.get(a[end])) && (r.dir == 0 || r.nstart == count.get(a[r.start]));
        }

        Run join(final Run r) {
            if (a[start] == a[r.start]) {
                nstart += r.nstart;
            }
            if (a[end] == a[r.end]) {
                nend += r.nend;
            }
            else {
                nend = r.nend;
            }
            end = r.end;
            if (dir == 0) {
                dir = r.dir;
            }
            if (dir == 0 && a[start] != a[end]) {
                dir = idx.get(a[end]) - idx.get(a[start]);
            }
            return this;
        }

        @Override
        public String toString() {
            return start + "(" + nstart + ") - " + end + '(' + nend + "): " + dir;
        }
    }

    static class State implements Comparable<State> {
        int[] b;
        int[] rv;
        State p;
        List<Run> runs;

        public State(final int[] b, final int[] rv, final State p, final List<Run> runs) {
            this.b = Arrays.copyOf(b, b.length);
            this.rv = rv;
            this.p = p;
            this.runs = runs;
        }

        @Override
        public int compareTo(final State o) {
            return runs.size() - o.runs.size();
        }

        @Override
        public String toString() {
            return Arrays.toString(b) + " - " + Arrays.toString(rv) + " - " + runs.size();
        }

        int getCount() {
            return p == null ? 0 : p.getCount() + 1;
        }
    }

    static void reverse(int x, int y) {
        while (x < y) {
            int t = a[x];
            a[x] = a[y];
            a[y] = t;
            x++;
            y--;
        }
    }

    static List<Run> runs() {
        final List<Run> l = new ArrayList<>();
        Run run = new Run(0);
        for (int i = 1; i < n; ++i) {
            final int t = idx.get(a[i]) - idx.get(a[i - 1]);
            if (Math.abs(t) > 1) {
                run.end = i - 1;
                l.add(run);
                run = new Run(i);
            }
            else if (t == 0) {
                run.nend++;
                if (run.dir == 0) {
                    run.nstart++;
                }
            }
            else {
                if (run.dir == 0) {
                    run.dir = t;
                }
                else if (run.dir != t || run.nend != count.get(a[i - 1])) {
                    run.end = i - 1;
                    l.add(run);
                    run = new Run(i);
                }
                run.nend = 1;
            }
        }
        run.end = n - 1;
        l.add(run);
        return l;
    }

    static void show() {
        if (!Arrays.equals(a, srt)) {
            System.out.println("bug!");
            System.out.println(Arrays.toString(a));
            throw new RuntimeException();
        }
        System.out.println("Sorted: " + Arrays.toString(a));
        System.out.println(rev.size() + " reversal(s):");
        for (int[] x : rev) {
            System.out.println(Arrays.toString(x));
        }
    }

    static void sort() {
        State bestest = null;
        final int[] a1 = Arrays.copyOf(a, n);
        final int[] sizes = {10, 20, 30, 50, 100, 200, 300, 500, 1000, 2000};

        for (int nb : sizes) {
            System.arraycopy(a1, 0, a, 0, n);
            ns = 1;
            best[0] = new State(a, null, null, runs());
            while (best[0].runs.size() > 1) {
                final State[] s = Arrays.copyOf(best, ns);
                ns = 0;
                for (State x : s) {
                    System.arraycopy(x.b, 0, a, 0, n);
                    final int m = x.runs.size();
                    for (int i = 0; i < m; ++i) {
                        for (int j = i; j < m; ++j) {
                            boolean b = false;
                            if (i > 0) {
                                final Run r = x.runs.get(j);
                                r.reverse();
                                b = x.runs.get(i - 1).canJoin(r);
                                r.reverse();
                            }
                            if (!b && j < m - 1) {
                                final Run r = x.runs.get(i);
                                r.reverse();
                                b = r.canJoin(x.runs.get(j + 1));
                                r.reverse();
                            }
                            if (!b) {
                                continue;
                            }
                            final List<Run> l = new ArrayList<>(x.runs);
                            final int rstart = l.get(i).start;
                            final int rend = l.get(j).end;
                            final int t = rstart + rend;
                            reverse(rstart, rend);
                            for (int k = i; k <= j; ++k) {
                                final Run r = x.runs.get(i + j - k).copy().reverse();
                                r.start = t - r.start;
                                r.end = t - r.end;
                                l.set(k, r);
                            }
                            if (j < m - 1 && l.get(j).canJoin(l.get(j + 1))) {
                                l.get(j).join(l.get(j + 1));
                                l.remove(j + 1);
                            }
                            if (i > 0 && l.get(i - 1).canJoin(l.get(i))) {
                                l.set(i - 1, l.get(i - 1).copy().join(l.get(i)));
                                l.remove(i);
                            }

                            if (ns < nb || l.size() < best[ns - 1].runs.size()) {
                                best[ns++] = new State(a, new int[]{rstart, rend}, x, l);
                                Arrays.sort(best, 0, ns);
                                if (ns > nb) {
                                    ns = nb;
                                }
                            }
                            reverse(rstart, rend);
                        }
                    }
                }

                if (ns == 0) {
                    for (State x : s) {
                        System.arraycopy(x.b, 0, a, 0, n);
                        final List<Run> l = new ArrayList<>(x.runs);
                        final int rstart = l.get(0).start;
                        final int rend = l.get(0).end;
                        final int t = rstart + rend;
                        reverse(rstart, rend);
                        final Run r = x.runs.get(0).copy().reverse();
                        r.start = t - r.start;
                        r.end = t - r.end;
                        l.set(0, r);

                        best[ns++] = new State(a, new int[]{rstart, rend}, x, l);
                        reverse(rstart, rend);
                    }
                    Arrays.sort(best, 0, ns);
                }
            }
            State r = null;
            for (int i = 0; i < ns; ++i) {
                if (Arrays.equals(best[i].b, srt)) {
                    r = best[i];
                    break;
                }
            }
            if (r == null) {
                final State x = best[0];
                System.arraycopy(x.b, 0, a, 0, n);
                reverse(0, n - 1);
                r = new State(a, new int[]{0, n - 1}, x, runs());
            }
            if (!Arrays.equals(r.b, srt)) {
                throw new RuntimeException("bug");
            }

            if (bestest == null || r.getCount() < bestest.getCount()) {
                bestest = r;
            }
        }

        while (bestest.p != null) {
            rev.add(bestest.rv);
            bestest = bestest.p;
        }
        Collections.reverse(rev);
        a = a1;
        for (int[] x : rev) {
            reverse(x[0], x[1]);
        }
        if (!Arrays.equals(a, srt)) {
            throw new RuntimeException("bug");
        }
    }

    static void init(final String s) {
        final String[] b = s.split(s.contains(",") ? "," : " ");
        n = b.length;
        a = new int[n];
        count = new HashMap<>();
        for (int i = 0; i < n; ++i) {
            a[i] = Integer.parseInt(b[i].trim());
            final Integer x = count.get(a[i]);
            count.put(a[i], x == null ? 1 : x + 1);
        }
        srt = Arrays.copyOf(a, n);
        Arrays.sort(srt);
        idx = new HashMap<>();
        int j = 0;
        for (int i = 0; i < n; ++i) {
            if (i == 0 || srt[i] != srt[i - 1]) {
                idx.put(srt[i], j++);
            }
        }
        rev = new ArrayList<>();
    }

    static void test5() {
        final String[] t = {"133, 319, 80, 70, 194, 333, 65, 21, 345, 142, 82, 491, 92, 167, 281, 386, 48, 101, 394, 130, 111, 139, 214, 337, 180, 24, 443, 35, 376, 13, 166, 59, 452, 429, 406, 256, 133, 435, 446, 304, 350, 364, 447, 471, 236, 177, 317, 342, 294, 146, 280, 32, 135, 399, 78, 251, 467, 305, 366, 309, 162, 473, 27, 67, 305, 497, 112, 399, 103, 178, 386, 343, 33, 134, 480, 147, 466, 244, 370, 140, 227, 292, 28, 357, 156, 367, 157, 60, 214, 280, 153, 445, 301, 108, 77, 404, 496, 3, 226, 37",
                "468, 494, 294, 42, 19, 23, 201, 47, 165, 118, 414, 371, 163, 430, 295, 333, 147, 336, 403, 490, 370, 128, 261, 91, 173, 339, 40, 54, 331, 236, 255, 33, 237, 272, 193, 91, 232, 452, 79, 435, 160, 328, 47, 179, 162, 239, 315, 73, 160, 266, 83, 451, 317, 255, 491, 70, 18, 275, 339, 298, 117, 145, 17, 178, 232, 59, 109, 271, 301, 437, 63, 103, 130, 15, 265, 281, 365, 444, 180, 257, 99, 248, 378, 158, 210, 466, 404, 263, 29, 117, 417, 357, 44, 495, 303, 428, 146, 215, 164, 99",
                "132, 167, 361, 145, 36, 56, 343, 330, 14, 412, 345, 263, 306, 462, 101, 453, 364, 389, 432, 32, 200, 76, 268, 291, 35, 13, 448, 188, 11, 235, 184, 439, 175, 159, 360, 46, 193, 440, 334, 128, 346, 192, 263, 466, 175, 407, 340, 393, 231, 472, 122, 254, 451, 485, 257, 67, 200, 135, 132, 421, 205, 398, 251, 286, 292, 488, 480, 56, 284, 484, 157, 264, 459, 6, 289, 311, 116, 138, 92, 21, 307, 172, 352, 199, 55, 38, 427, 214, 233, 404, 330, 105, 223, 495, 334, 169, 168, 444, 268, 248",
                "367, 334, 296, 59, 18, 193, 118, 10, 276, 180, 242, 115, 233, 40, 225, 244, 147, 439, 297, 115, 354, 248, 89, 423, 47, 458, 64, 33, 463, 142, 5, 13, 89, 282, 186, 12, 70, 289, 385, 289, 274, 136, 39, 424, 174, 186, 489, 73, 296, 39, 445, 308, 451, 384, 451, 446, 282, 419, 479, 220, 35, 419, 161, 14, 42, 321, 202, 30, 32, 162, 444, 215, 218, 102, 140, 473, 500, 480, 402, 1, 1, 79, 50, 54, 111, 189, 147, 352, 61, 460, 196, 77, 315, 304, 385, 275, 65, 145, 434, 39",
                "311, 202, 126, 494, 321, 330, 290, 28, 400, 84, 6, 160, 432, 308, 469, 459, 80, 48, 292, 229, 191, 240, 491, 231, 286, 413, 170, 486, 59, 54, 36, 334, 135, 39, 393, 201, 127, 95, 456, 497, 429, 139, 81, 293, 359, 477, 404, 129, 129, 297, 298, 495, 424, 446, 57, 296, 10, 269, 350, 337, 39, 386, 142, 327, 22, 352, 421, 32, 171, 452, 2, 484, 337, 359, 444, 246, 174, 23, 115, 102, 427, 439, 71, 478, 89, 225, 7, 118, 453, 350, 109, 277, 338, 474, 405, 380, 256, 228, 277, 3"};
        int r = 0;
        for (String s : t) {
            init(s);
            sort();
            System.out.println(rev.size());
            r += rev.size();
        }
        System.out.println("total: " + r);
    }

    public static void main(final String... args) throws IOException {
        System.out.print("Input: ");
        final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        final String s = br.readLine();
        final long t = System.currentTimeMillis();
        if (s.isEmpty()) {
            System.out.println("Running tests");
            test5();
        }
        else {
            init(s);
            sort();
            show();
        }
        System.out.println("Time: " + (System.currentTimeMillis() - t + 500) / 1000 + " sec");
    }
}

Đầu vào là danh sách các số được phân tách bằng dấu phẩy và / hoặc dấu cách (từ stdin). Nếu đầu vào trống, chương trình sẽ chạy 5 bài kiểm tra. Mỗi người mất khoảng 40 giây ở đây.


Điều thú vị là số lần đảo ngược trên trường hợp thử nghiệm thứ 5 đã không cải thiện với phiên bản mới. Những người khác cải thiện khá nhiều. Tôi rất vui vì bạn đã quyết định cho nó đi tiếp :)
Stewie Griffin

@StewieGriffin cảm ơn, bạn đã giúp tôi thổi qua 20k :) Tôi nghĩ rằng tôi đã có một chút may mắn với trường hợp cuối cùng trước đây. Một cách tiếp cận ngẫu nhiên có thể sẽ cho kết quả thậm chí tốt hơn.
aditsu

5

Một động tác brute-force sau đó chọn sắp xếp (cũng là giải pháp ngây thơ), 90 + 89 + 88 + 87 + 89 = 443 di chuyển

let doReverse = (a, l, r) => {
  a.splice(l, r - l, ...a.slice(l, r).reverse());
};
let selectSubVectorReverseSort = a => {
  let log = [];

  for (let i = 0, l = a.length; i < l; i++) {
    let j, p = i;
    for (j = i; j < l; j++) {
      if (a[j] < a[p]) p = j;
    }
    if (p === i) continue;
    log.push([i, p + 1]);
    doReverse(a, i, p + 1);
  }
  return log;
};

let a = JSON.parse(`[${readline()}]`);
let copiedArray = a => a.map(x => x);
let minLog = selectSubVectorReverseSort(copiedArray(a));
for (let i = 0, l = a.length; i < l; i++) {
  for (let j = i + 1; j < l; j++) {
    let b = copiedArray(a);
    doReverse(b, i, j + 1);
    let log = [[i, j + 1], ...selectSubVectorReverseSort(b)];
    if (log.length < minLog.length) minLog = log;
  }
}

print(minLog.length);

cho mỗi lần di chuyển đầu tiên có thể, hãy thử nó, và sau đó, thực hiện sắp xếp lựa chọn.

Vâng, đây là một giải pháp ngây thơ khác.

Tôi không chắc đây có phải là chỉnh sửa hay bài đăng khác không, nhưng có vẻ như giải pháp này quá đơn giản, vì vậy chỉnh sửa được chọn.


Sắp xếp lựa chọn (Giải pháp ngây thơ), 92 + 93 + 95 + 93 + 96 = 469 di chuyển

let log = [];
let doReverse = (a, l, r) => {
  log.push([l, r]);
  a.splice(l, r - l, ...a.slice(l, r).reverse());
}

let a = JSON.parse(`[${readline()}]`);
for (let i = 0, l = a.length; i < l; i++) {
  let j, p = i;
  for (j = i; j < l; j++) {
    if (a[j] < a[p]) p = j;
  }
  if (p === i) continue;
  doReverse(a, i, p + 1);
}
print(log.length)

Một giải pháp ngây thơ sử dụng sắp xếp lựa chọn.

phải có một số giải pháp tốt hơn, nhưng đăng bài này vì tôi không tìm thấy một tốt hơn (mà không cần tìm kiếm brute-force).

(Mã trên là JavaScript Shell )

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.