• Какой алгоритм использовать для определения минимального числа перестановок карт в колоде?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Правильный ответ - 52-<длина наибольшей общей подпоследовательности>.
    Выводится он так:
    1) Ни одну карту нет смысла двигать 2 раза. Т.е. ответ 52-<количество неподвижных карт>
    2) Неподвижные карты находятся в том же порядке в обеих колодах, следовательно они образуют наибольшую общую подпоследовательность.

    Наибольшая общая подпоследовательность - вообще-то это их обработки строчек тема, будем считать что у нас даны 2 52-символьные строки, один символ-одна карта, все символы разные. НОП - это такая наибольшая строка, которая останется, если выкинуть из первой и второй строки какие-то символы. Ищется она за квадратичную сложность (в данном случае - моментально, строчки-то фиксированной длины) динамическим программированием.

    F(i, j) - длина наибольшей общей подстроки у префиксов длины i у первой строки и длины j у второй.

    База F(0,*)=F(*,0)=0

    Переход: F(i,j) = max(F(i-1,j), F(i,j-1), F(i-1,j-1)+1). Третий вариант рассматривается только, если i-ый символ в первой строке и j-ый во второй равны.

    Ответ - 52-F(52,52) для вашей задачи

    Если надо выдать куда что перемещать, то задача чуть сложнее. Динамика модифицируется сохранением, какой из трех вариантов был выбран, чтобы потом восстановить НОП. Эти карты помечаются как неподвижные. Потом, для всех карт во второй колоде найдите их места в первой колоде. А потом, тупо, перемещайте подвижные карты по одной на нужные места в возрастающем порядке результирующих мест. Тогда не надо будет вообще учитывать пока не перемещенные карты.
    Ответ написан
    Комментировать
  • Какой алгоритм использовать для определения минимального числа перестановок карт в колоде?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Мои мысли на тему и получившийся алгоритм:
    - обозначим для простоты карты их порядковыми номерами в отсортированной колоде, Ai;
    - каждой карте сопоставим расстояние до её конечной желаемой позиции, равное i - Ai;
    - перестановка карты с позиции i на позицию j меняет её расстояние на j - i, и одновременно на sign(i - j) меняет расстояния карт между i и j;
    - перестановка выгодна если она уменьшает суммарное расстояние, которое потребуется пройти картам после неё;
    - для текущей позиции существует по меньшей мере одна наиболее выгодная перестановка -- такая, которая максимально уменьшает оставшееся расстояние; найти её можно тупым перебором исходной и конечной позиции переставляемой карты (но, может быть, можно и быстрее);
    - совершая на каждом шаге наиболее выгодную перестановку мы, скорее всего, упорядочим карты за минимальное число перестановок.

    Код на c:
    #include <limits.h>
    #include <stdio.h>
    #include <string.h>
    
    #define N (sizeof(a) / sizeof(a[0]))
    
    inline int sign(int d)
    {
            if (d == 0)
                    return 0;
            return d < 0 ? -1 : 1;
    }
    
    inline int abs(int v)
    {
            return v < 0 ? -v : v;
    }
    
    int main()
    {
            int a[] = {2, 1, 3, 4, 0};
            int q[N];
    
            for (;;) {
                    int best_profit = INT_MIN;
                    int best_src = -1;
                    int best_dst = -1;
                    int i, src, dst, tmp;
    
                    for (i = 0; i < N; ++i)
                            q[i] = i - a[i];
    
                    for (src = 0; src < N; ++src)
                            for (dst = 0; dst < N; ++dst) {
                                    int d = sign(dst - src);
                                    int profit = abs(q[src]) - abs(q[src] + dst - src);
    
                                    //printf("...%d -> %d: profit = %d", src, dst, profit);
    
                                    for (i = src + d; i != dst + d; i += d) {
                                            if (sign(q[i]) == d) {
                                                    ++profit;
                                                    //printf(" + 1");
                                            } else {
                                                    --profit;
                                                    //printf(" - 1");
                                            }
                                    }
                                    //printf(" = %d\n", profit);
                                    if (profit > best_profit) {
                                            best_src = src;
                                            best_dst = dst;
                                            best_profit = profit;
                                            //printf("... -- new best!\n");
                                    }
                            }
                    printf("%d -> %d (profit = %d)\n", best_src, best_dst, best_profit);
                    if (best_profit == 0)
                            break;
                    tmp = a[best_src];
                    if (best_dst < best_src)
                            memmove(a + best_dst + 1, a + best_dst, (best_src - best_dst) * sizeof(int));
                    else
                            memmove(a + best_src, a + best_src + 1, (best_dst - best_src) * sizeof(int));
                    a[best_dst] = tmp;
    
                    for (i = 0; i < N; ++i)
                            printf("%d ", a[i]);
                    printf("\n");
            }
            return 0;
    }
    Ответ написан
    Комментировать
  • Как лучше найти пересечение списков?

    svfat
    @svfat
    ☺Нужен VPS? Два месяца бесплатно. Смотри профиль☺
    set будет работать быстрее всего
    Ответ написан
    Комментировать
  • Как лучше найти пересечение списков?

    Можно изначально хранить данные в set.
    Ответ написан
    Комментировать
  • Как разделить строку на список с элементами, сгруппированными по парам (Python)?

    @brake
    >>> a = "abcdefgh"
    >>> map(''.join, zip(a[::2], a[1::2]))
    ['ab', 'cd', 'ef', 'gh']
    >>> map(''.join, zip(*([iter(a)]*2)))
    ['ab', 'cd', 'ef', 'gh']
    Ответ написан
    1 комментарий
  • Как разделить строку на список с элементами, сгруппированными по парам (Python)?

    bobrovskyserg
    @bobrovskyserg
    s = "0123456789"
    print([s[i:i + 2] for i in range(0, len(s), 2)])
    Ответ написан
    Комментировать
  • Что нужно, чтобы стать разработчиком игр?

    Tiendil
    @Tiendil
    Разработчик ПО.
    Нужно желание и знание ЯП.
    Разработка игр ничем принципиально не отличается от любой другой области. Особенно, с точки зрения программиста.

    Игры сейчас пишут на чём угодно и для чего угодно.
    Доля успешных проектов такая же как и для любой другой области — мизерная.
    Знание математики ещё никому нигде никогда не вредило. В играх, как и в большинстве другого софта, она в большей части проекта не нужна. Необходимый минимум легко гуглится.

    В СНГ это перспективно также, как и вне СНГ — рынок игр международный, для локальных рынков их делают единицы.

    Стоит или нет — решайте сами. Этот вопрос из разряда «нравится / не нравится».
    Ответ написан
    Комментировать