Программирование для молодых таблиц

Странный вопрос:
Я участвую в конкурсе по решению проблем в моей школе, и они позволяют нам использовать компьютер. Поскольку я единственный в соревновании, кто знает, как кодировать, я использую программы на C и Pascal, чтобы быстрее решать проблемы. Я сделал это с помощью упражнений с псевдокодом в код, алгоритмов, проверки гипотезы Коллатца и тому подобного.
Итак, вчера я готовился к следующему соревнованию (18 апреля) и увидел упражнение по таблицам Юнга. Это было сформулировано так (я сделаю все возможное, чтобы перевести с итальянского):
"Диаграммы Ferrers - это конфигурация из N блоков, распределенных в одной или нескольких горизонтальных строках, выровненных по левому краю и сконфигурированных так, чтобы каждая строка содержала равное или меньшее количество блоков, чем строка над ней. Эти конфигурации также могут быть описаны списком номер коробки, как на этом изображении:
ferrers diagrams
(источник: olimpiadiproblemsolving.it)

Таблица Юнга представляет собой диаграмму Феррера из N блоков, заполненных целыми числами от 1 до N. Пример:
young tableaux
(источник: olimpiadiproblemsolving.it)

Если числа в полях отсортированы так, что они расположены в порядке возрастания по строкам и столбцам, таблица является "стандартной" (пример: первая, третья и пятая таблицы). В стандартных таблицах первый блок первой строки всегда содержит 1. N всегда находится в крайнем левом блоке в одной из строк диаграммы.


ПРОБЛЕМА

Рассмотрим диаграмму [6,3,2,1,1,1] Ferrers:
1) Если 6 зафиксировано в 6-м блоке 1-го ряда, а 11 - в последнем блоке 1-го столбца, каким образом вы можете заполнить диаграмму стандартным способом?

2) Если в 6-м блоке 1-го ряда зафиксировано 7, а в последнем блоке 1-го столбца - 11, каким образом вы можете заполнить диаграмму стандартным способом?

3) Если 8 зафиксировано в 6-м блоке 1-го ряда, а 11 - в последнем блоке 1-го столбца, каким образом вы можете заполнить диаграмму стандартным способом? "

Я пытался закодировать решение с помощью матрицы, заполненной этими числами и с "-1" в качестве "символа конца строки", но я застрял. Как я могу кодировать "заполнить его всеми возможными способами, чтобы таблица была стандартной?".

Ответы

Ответ 1

Вот пример решения с использованием SWI-Prolog для первой проблемы:

:- use_module(library(clpfd)).

tableau(Ts) :-
        Ts = [[A,B,C,_,_,F],
              [G,H,I],
              [J,K],
              [L],
              [M],
              [N]],
        A = 1,
        maplist(ascending, Ts),
        ascending([A,G,J,L,M,N]),
        ascending([B,H,K]),
        C #< I,
        append(Ts, Vs),
        all_different(Vs),
        Vs ins 1..14,
        F = 6,
        N = 11,
        label(Vs).

ascending(Vs) :- chain(Vs, #<).

Ответ заключается в том, что есть два способа завершить таблицу:

?- tableau(Ts), maplist(writeln, Ts).
[1,2,3,4,5,6]
[7,12,13]
[8,14]
[9]
[10]
[11]
    Ts = [[1, 2, 3, 4, 5, 6], [7, 12, 13], [8, 14], [9], [10], [11]] ;
[1,2,3,4,5,6]
[7,12,14]
[8,13]
[9]
[10]
[11]
    Ts = [[1, 2, 3, 4, 5, 6], [7, 12, 14], [8, 13], [9], [10], [11]] ;
false.

Ответ 2

Чтобы решить эту проблему, я бы использовал Программу ограничения (CP). Таблицы Young - фактически одна из стандартных проблем, которые я пытаюсь решить при изучении новой системы CP. Вот список реализаций до сих пор: http://hakank.org/common_cp_models/#youngtableaux.

Я изменил "обычную" модель MiniZinc с некоторыми дополнительными ограничениями для ваших конкретных вопросов. Смотрите полную модель здесь:    http://www.hakank.org/minizinc/young_tableaux_stack_overflow.mzn

(MiniZinc очень высокий уровень и легко экспериментирует с такими проблемами.)

Кратко о представлении в модели: Для проблемы размера n (разбиение на n), квадраты представлены как сетка ( "x", размер n раз n) со значениями от 1 до n + 1, где каждая строка и столбец сортируются в порядке возрастания; поэтому n + 1 сортируется последним и действует как пустое значение. Затем структура раздела ( "p" ) обрабатывается в соответствии с структурой Young/Ferrer (подробности см. В модели).

Каждый из трех вопросов имеет два дополнительных ограничения (по сравнению со стандартной формулировкой проблемы):

  • определенное число должно быть в 6-ом поле первой строки  Дополнительное ограничение     x [1,6] = 6% или 7 или 8

  • и 11 должны находиться в последнем поле первого столбца  Это немного сложнее, но мой путь - это, т.е.  что в первом столбце 11 должно быть последнее из значений, меньших n + 1,  то есть все значения, следующие в столбце, равны n + 1:

     exists(j in 1..n) (
          x[j,1] = 11 /\ forall(k in j+1..n) (x[k,1] = n+1)
     )
    

Итак, если я правильно понял вопросы, ответы: 1) 2 решения 2) 10 решений 3) 30 решений

Ответ 3

Без использования программы я считаю, что ответ на 1) равен 2. Получение этого вручную может привести кого-то к алгоритмическому решению.

Первая строка начинается с 1 и заканчивается на 6. Поэтому числа, которые могут перейти в строку 1, должны удовлетворять этому условию: 1 < x < 6. Из 14 цифр, которые могут войти в эту таблицу, только 4 удовлетворяют этому условию, и они: 2 3 4 5. Это означает, что строка 1 должна быть: 1 2 3 4 5 6.

Первый столбец начинается с 1 и заканчивается на 11. Числа, которые могут попасть в первый столбец, должны удовлетворять аналогичному условию: 1 < y < 11. Из оставшихся неназначенных чисел только 4 соответствуют этому условию: 7 8 9 10. Это приводит к тому, что первая колонка составляет: 1 7 8 9 10 11.

Теперь осталось всего 3 оставшихся номера: 12 13 14. Есть два способа организовать их в остальных 3 ячейках таблицы. Они могут быть расположены:

12 13

14

- или -

12 14

13

Попытка справиться с этим в коде, можно пойти по маршруту грубой силы или взглянуть на методы распространения ограничений и обратного отслеживания. Вот почему кто-то предложил Пролог раньше. Другим языком для просмотра будет Python.

Ответ 4

Это проблема программирования логического ограничения. Используйте язык программирования Prolog. Пролог Sicstus с библиотекой clpfd.

Учитывая макет как таковой:

ABCDEF
GHI
JK
L
M
N

- код -

use_module(library(clpfd)).

all_different([A,B,C,D,E,F,G,H,I,J,K,L,M,N]),
domain([A,B,C,D,E,F,G,H,I,J,K,L,M,N],1,14),
B #> A, C #> B, D #> C, E #> D, F #> E,
G #> A, H #> B, H #> G, I #> G, I #> H,  I #> C,
J #> A, J #> G, 
L #> A, L #> G, L #> J,
M #> A, M #> G, M #> J, M #> L,
N #> A, N #> G, N #> J, N #> L, N #> M.

A=1
F=6
N=11

Ответ 5

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