Все возможные комбинации длины 8 в массиве 2d

Я пытался решить проблему в комбинациях. У меня есть матрица 6X6, я пытаюсь найти все комбинации длины 8 в матрице.

Мне нужно перемещаться от соседа к соседу из каждой строки, позиции столбца, и я написал рекурсивную программу, которая генерирует комбинацию, но проблема в том, что она также генерирует много дубликатов и, следовательно, неэффективна. Я хотел бы знать, как я могу исключить вычисление дубликатов и сэкономить время.

int a={{1,2,3,4,5,6},
   {8,9,1,2,3,4},
   {5,6,7,8,9,1},
   {2,3,4,5,6,7},
   {8,9,1,2,3,4},
   {5,6,7,8,9,1},
  }

 void genSeq(int row,int col,int length,int combi)
 {
    if(length==8)
    {
      printf("%d\n",combi);
      return;
    }
    combi = (combi * 10) + a[row][col];
    if((row-1)>=0)

    genSeq(row-1,col,length+1,combi);

if((col-1)>=0)

    genSeq(row,col-1,length+1,combi);

if((row+1)<6)

    genSeq(row+1,col,length+1,combi);

if((col+1)<6)

    genSeq(row,col+1,length+1,combi);

if((row+1)<6&&(col+1)<6)

    genSeq(row+1,col+1,length+1,combi);

if((row-1)>=0&&(col+1)<6)

    genSeq(row-1,col+1,length+1,combi);

if((row+1)<6&&(row-1)>=0)

    genSeq(row+1,col-1,length+1,combi);

if((row-1)>=0&&(col-1)>=0)

    genSeq(row-1,col-1,length+1,combi);
   }

Я также думал о написании динамической программы, основанной на рекурсии с запоминанием. Это лучший выбор?? если да, то я не понимаю, как реализовать это в рекурсии. Я действительно зашел в тупик с подходом???

Спасибо

Изменить Например, результат 12121212,12121218,12121219,12121211,12121213.

ограничения заключаются в том, что вы должны двигаться к своему соседу из любой точки, вы должны начинать с каждой позиции в матрице, то есть с каждой строки, столбца. вы можете двигаться по одному шагу за раз, то есть вправо, влево, вверх, вниз и в обе диагональные позиции. Проверьте условия if. то есть, если вы находитесь в (0,0), вы можете перейти либо к (1,0), либо к (1,1), либо (0,1), то есть к трем соседям. если вы находитесь в (2,2), вы можете перейти к восьми соседям.
и так далее...


person CodeJunki    schedule 23.12.2010    source источник
comment
как вы это называете, и есть ли у вас образец вывода? Когда вы говорите длину 8, существуют ли какие-либо ограничения (в направлении), которые применяются, или это любое направление из любой позиции?   -  person Nim    schedule 23.12.2010
comment
ограничения заключаются в том, что вы должны двигаться к своему соседу из любой точки, вы должны начинать с каждой позиции в матрице, то есть с каждой строки, столбца. вы можете двигаться по одному шагу за раз, то есть вправо, влево, вверх, вниз и в обе диагональные позиции. Проверьте условия if.   -  person CodeJunki    schedule 23.12.2010


Ответы (4)


Чтобы устранить дубликаты, вы можете преобразовать 8-значные последовательности в 8-значные целые числа и поместить их в хеш-таблицу.

Мемоизация может быть хорошей идеей. Вы можете запомнить для каждой ячейки матрицы все возможные комбинации длины 2-7, которые можно из нее получить. Идя назад: сначала сгенерируйте для каждой ячейки все последовательности из 2 цифр. Затем на основе 3 цифр и т.д.

ОБНОВЛЕНИЕ: код на Python

# original matrix
lst = [
   [1,2,3,4,5,6],
   [8,9,1,2,3,4],
   [5,6,7,8,9,1],
   [2,3,4,5,6,7],
   [8,9,1,2,3,4],
   [5,6,7,8,9,1]]

# working matrtix; wrk[i][j] contains a set of all possible paths of length k which can end in lst[i][j]
wrk = [[set() for i in range(6)] for j in range(6)]

# for the first (0rh) iteration initialize with single step paths
for i in range(0, 6):
    for j in range(0, 6):
        wrk[i][j].add(lst[i][j])

# run iterations 1 through 7
for k in range(1,8):
    # create new emtpy wrk matrix for the next iteration
    nw = [[set() for i in range(6)] for j in range(6)]

    for i in range(0, 6):
        for j in range(0, 6):
            # the next gen. wrk[i][j] is going to be based on the current wrk paths of its neighbors
            ns = set()
            if i > 0:
                for p in wrk[i-1][j]:
                    ns.add(10**k * lst[i][j] + p)
            if i < 5:
                for p in wrk[i+1][j]:
                    ns.add(10**k * lst[i][j] + p)
            if j > 0:
                for p in wrk[i][j-1]:
                    ns.add(10**k * lst[i][j] + p)
            if j < 5:
                for p in wrk[i][j+1]:
                    ns.add(10**k * lst[i][j] + p)

            nw[i][j] = ns
    wrk = nw

# now build final set to eliminate duplicates
result = set()

for i in range(0, 6):
    for j in range(0, 6):
        result |= wrk[i][j]

print len(result)
print result
person MK.    schedule 23.12.2010
comment
я не хочу устранять дубликаты после их вычисления, а не перед их вычислением. Я такого рода запоминание выполнит эту работу, но все же медленнее, я думал о сохранении последовательности, сгенерированной для одной начальной позиции, а затем удалить первый элемент и новый элемент, т.е. если моя последовательность равна 12345678, тогда удалите 1 и добавьте новый элемент в конце . экономия 7 шагов в рекурсии. :) - person CodeJunki; 23.12.2010
comment
@CodeJunki, вы не можете предотвратить дублирование; вам нужно создать один, прежде чем вы узнаете, что это дубликат :) Прочтите второй абзац еще раз - оптимизация заключается в том, чтобы сначала создать короткие последовательности, а затем увеличить их, добавляя все возможные способы прибытия в ячейку (т.е. есть 3 способа для добраться до угловой клетки, 8 до средней клетки и т. д.). Это классическое решение для динамического программирования. - person MK.; 23.12.2010

Есть МНОГО способов сделать это. Прохождение каждой комбинации является вполне разумным первым подходом. Все зависит от ваших требований. Если ваша матрица небольшая и эта операция не чувствительна ко времени, то проблем нет.

Я не очень разбираюсь в алгоритмах, но я уверен, что есть действительно умные способы сделать это, которые кто-нибудь опубликует после меня.

Кроме того, в Java при использовании CamelCase имена методов должны начинаться со строчной буквы.

person Falmarri    schedule 23.12.2010
comment
Ну, это зависит от того, что вы хотите. Есть оптимизации, которые вы можете сделать на основе того, что вы знаете о выводе. - person Falmarri; 23.12.2010

int a={{1,2,3,4,5,6}, {8,9,1,2,3,4}, {5,6,7,8,9,1}, {2,3,4,5,6,7}, {8,9,1,2,3,4}, {5,6,7,8,9,1}, }

Под длиной вы подразумеваете суммирование комбинации элементов матрицы, в результате чего получается 8.
т. е. элементы для суммирования 8 с самой строкой и с другими элементами строки.
Из строки 1 = { {2,6}, {3,5}, } и теперь элементы строки 1 со строкой 2 и так далее. Это то, что вы ожидаете?

person Mahesh    schedule 23.12.2010
comment
Я думаю, он хочет последовательность из 8 цифр. - person MK.; 23.12.2010

Вы можете думать о своей матрице, как об одномерном массиве - здесь неважно ("разместите" строки одну за другой). Для одномерного массива вы можете написать такую ​​функцию (при условии, что вы должны распечатать комбинации)

f(i, n) prints all combinations of length n using elements a[i] ... a[last].

Он должен пропустить некоторые элементы от a[i] до a[i + k] (для всех возможных k), вывести a[k] и сделать рекурсивный вызов f(i + k + 1, n - 1).

person crazylammer    schedule 27.12.2010