minHeight что-нибудь делает?

Здесь много длинных фрагментов кода. Лучше думать больше и меньше кода.

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

Как бы вы это сделали без кода? Получите 10 карт и напишите цифры от 0 до 9. Нарисуйте строку из 9 квадратов на столе. Выберите карту. Поместите его в первый квадрат, другой во второй и т. Д. Когда вы выбрали 9, у вас есть свой первый номер. Теперь удалите последнюю карту и замените ее каждой возможной альтернативой. (В этом случае всего 1). Каждый раз, когда все квадраты заполняются, у вас есть еще один номер. Когда вы сделали все альтернативы для последнего квадрата, сделайте это для последнего 2. Повторите с последними 3 и т. Д., Пока вы не рассмотрите все альтернативы для всех ящиков.

Написание сжатой программы для этого - выбор простых структур данных. Используйте массив символов для строки из 9 квадратных.

Используйте другой массив для набора карт. Чтобы удалить элемент из набора размера N, хранящегося в массиве A [0 .. N-1], мы используем старый трюк. Скажем, элемент, который вы хотите удалить, - A [I]. Сохраните значение A [I] в сторону. Затем скопируйте последний элемент A [N-1] «вниз», переписывая A [I]. Новый набор A [0 .. N-2]. Это прекрасно работает, потому что нас не интересует порядок в наборе.

Остальное - использовать рекурсивное мышление для перечисления всех возможных альтернатив. Если я знаю, как найти все варианты из набора символов размера M в строку размера N, то для получения алгоритма просто выберите каждый возможный символ для первой позиции строки, затем повторите выбор, чтобы выбрать остальную часть N-1 символов из оставшегося набора размеров M-1. Мы получаем хорошую 12-строчную функцию:

#include <stdio.h>

// Select each element from the given set into buf[pos], then recur
// to select the rest into pos+1... until the buffer is full, when
// we print it.
void select(char *buf, int pos, int len, char *set, int n_elts) {
  if (pos >= len)
    printf("%.*s\n", len, buf);  // print the full buffer
  else
    for (int i = 0; i < n_elts; i++) {
      buf[pos] = set[i];         // select set[i] into buf[pos]
      set[i] = set[n_elts - 1];  // remove set[i] from the set
      select(buf, pos + 1, len, set, n_elts - 1); // recur to pick the rest
      set[n_elts - 1] = set[i];  // undo for next iteration
      set[i] = buf[pos];
    }
}

int main(void) {
  char buf[9], set[] = "0123456789";
  select(buf, 0, 9, set, 10); // select 9 characters from a set of 10
  return 0;
}

Вы не упомянули, нормально ли положить ноль в первую позицию. Предположим, что это не так. Поскольку мы хорошо понимаем алгоритм, легко избежать выбора нуля в первую позицию. Просто пропустите эту возможность, заметив, что !pos в C имеет значение 1, если pos равно 0 и 0. Если вам не нравится эта слегка неясная идиома, попробуйте (pos == 0 ? 1 : 0) как более читаемую замену:

#include <stdio.h>

void select(char *buf, int pos, int len, char *set, int n_elts) {
  if (pos >= len)
    printf("%.*s\n", len, buf);
  else
    for (int i = !pos; i < n_elts; i++) {
      buf[pos] = set[i];
      set[i] = set[n_elts - 1];
      select(buf, pos + 1, len, set, n_elts - 1);
      set[n_elts - 1] = set[i];
      set[i] = buf[pos];
    }
}

int main(void) {
  char buf[9], set[] = "0123456789";
  select(buf, 0, 9, set, 10);
  return 0;
}
30
задан Matt 13 September 2011 в 20:41
поделиться