Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Kursovaya_Diskretnaya_matematika.docx
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
344 Кб
Скачать
☆

1 Комбинаторика. Общие понятия.

Комбинаторика (Комбинаторный анализ) — раздел математики, изучающий дискретные объекты, множества (сочетания, перестановки, размещения и перечисления элементов) и отношения на них (например, частичного порядка). Комбинаторика связана со многими другими областями математики — алгеброй, геометрией, теорией вероятностей и имеет широкий спектр применения в различных областях знаний (например в генетике, информатике, статистической физике).

Термин «комбинаторика» был введён в математический обиход Лейбницем, который в 1666 году опубликовал свой труд «Рассуждения о комбинаторном искусстве».

Иногда под комбинаторикой понимают более обширный раздел дискретной математики, включающий, в частности, теорию графов.

Для формулировки и решения комбинаторных задач используют различные модели комбинаторных конфигураций. Примерами комбинаторных конфигураций являются:

  • Размещением из n элементов по k называется упорядоченный набор из k различных элементов некоторого n-элементного множества;

  • Перестановкой из n элементов (например чисел 1,2,…,n) называется всякий упорядоченный набор из этих элементов. Перестановка также является размещением из n элементов по n;

  • Сочетанием из n по k называется набор k элементов, выбранных из данных n элементов. Наборы, отличающиеся только порядком следования элементов (но не составом), считаются одинаковыми, этим сочетания отличаются от размещений;

  • Композицией числа n называется всякое представление n в виде упорядоченной суммы целых положительных чисел;

  • Разбиением числа n называется всякое представление n в виде неупорядоченной суммы целых положительных чисел.

К разделам комбинаторики относят:

  • Перечислительная комбинаторика;

  • Структурная комбинаторика;

  • Экстремальная комбинаторика;

  • Теория Рамсея;

  • Вероятностная комбинаторика;

  • Топологическая комбинаторика;

  • Инфинитарная комбинаторика.

2. Перестановки.

Рисунок 1 - перестановки

Перестановкой называется упорядоченный набор элементов. Во многих алгоритмических задачах из этого каталога требуется найти наилучший способ упорядочения набора объектов. В качестве примеров можно назвать задачу коммивояжера (определение порядка посещения п городов, имеющего наименьшую стоимость),задачу уменьшения ширины ленты (упорядочивание вершин графа в линию таким образом, чтобы минимизировать длину самого длинного ребра) и задачу изоморфизма графа (упорядочивание вершины графа таким образом, чтобы он был идентичным другому графу). Любой алгоритм для предоставления точного решения таких задач должен создавать в процессе решения последовательность перестановок. Из п элементов можно создать п\ перестановок. С увеличением п количество перестановок возрастает так быстро, что не стоит надеяться сгенерировать все перестановки для п > 12, т. к. 12! = 479 001 600. Подобные числа должны охладить пыл любого человека, пытающегося решить задачу методом исчерпывающего перебора, и помочь объяснить важность генерирования случайных перестановок.

2.1 Лексикографический порядок

Лексикографический порядок означает, что элементы отсортированы, и часто является наиболее естественным способом генерирования комбинаторных объектов. Перестановки{1, 2, 3} располагаются в лексикографическом порядке таким образом: {}, {1}, {1, 2}, {1, 2, 3}, {1, 3}, {2}, {2, 3} и {3}. Но генерирование подмножеств в лексикографическом порядке оказы­вается на удивление трудной задачей. Поэтому не стоит использовать этот подход, если только у вас нет какой-либо важной причины для этого.

Ниже представлен код на языке C#, который решает поставленные нам задачи

//--------------------------------------------------------------------------------------генерация всех перестановок

private void button1_Click(object sender, EventArgs e)

{

int N;

//Ввод N с защитой от дурака

if (Int32.TryParse(textBox1.Text, out N) && N >= 1)

{

string s = System.String.Empty;

int i = 0, j = 0;

int[] a = new int[N];

for (; i < N; i++)

a[i] = i+1;

while (true)

{

s = GetString(a);

listBox1.Items.Add(s);

//Находим самый правый индекс, где a[i - 1] < a[i]

for (i = N - 1; i > 0 && a[i - 1] > a[i]; i--) ;

//Если i = 0 - все перестановки найдены - выходим

if (i == 0) break;

//Находим a[j] - наименьший элемент справа от a[i - 1] и больший его

for (j = N - 1; a[i - 1] > a[j]; j--) ;

//Меняем местами a[i - 1] и a[j]

Swap(ref a[i - 1], ref a[j]);

//реверс строки от позиции i до конца

for (int k = i, r = N - 1; r > k; k++, r--)

Swap(ref a[r], ref a[k]);

}

}

else

{

textBox1.Text = "";

var result = MessageBox.Show("Порядок группы перестановок - натуральное число N >= 1",

"Ошибка ввода N",

MessageBoxButtons.OK,

MessageBoxIcon.Error);

}

}

//---------------------------------------------------------------------------------------получение перестановки по номеру

private void button2_Click(object sender, EventArgs e)

{

int N;

long k;

//Ввод N и k с защитой от дурака

if (Int32.TryParse(textBox2.Text, out N) && N >= 1)

{

long[] Factorials = new long[N];

GetFactorialsArray(ref Factorials, N);

if (Int64.TryParse(textBox3.Text, out k) && k >= 1 && k <= Factorials[N - 1])

{

bool[] used = new bool[N];

for (int i = 0; i < N; i++)

used[i] = false;

int[] a = new int[N];

k--;

for (int i = 0; i < N - 1; i++)

{

int x = Convert.ToInt32(k / Factorials[N - 2 - i]);

k %= Factorials[N - 2 - i];

int count = -1, j = 0;

for ( ; count != x; j++) //пока не отсчитаем х

if (!used[j]) count++; //считаем неиспользованные числа

a[i] = j;

used[j-1] = true;

}

for (int i = 0; i < N; i++)

if (!used[i])

{

a[N - 1] = i + 1;

}

string s = GetString (a);

textBox4.Text = s;

}

else

{

textBox3.Text = "";

var result = MessageBox.Show("Номер перестановки - натуральное число 1 <= k <= N!",

"Ошибка ввода k",

MessageBoxButtons.OK,

MessageBoxIcon.Error);

}

}

else

{

textBox2.Text = "";

var result = MessageBox.Show("Порядок группы перестановок - натуральное число N >= 1",

"Ошибка ввода N",

MessageBoxButtons.OK,

MessageBoxIcon.Error);

}

}

//-------------------------------------------------------------------------------------- получение номера по перестановке

private void button3_Click(object sender, EventArgs e)

{

string s = textBox5.Text;

string[] words = s.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries);

int N = words.Length;

int[] a = new int[N];

for (int i = 0; i < N; i++)

a[i] = Convert.ToInt32(words[i]);

//если введенная последовательность является перестановкой

if (CheckSequence(a))

{

long[] Factorials = new long[N];

GetFactorialsArray(ref Factorials, N);

long k = 0; //здесь будет номер

//массив использованных/неиспользованных чисел

bool[] used = new bool[N];

for (int i = 0; i < N; i++)

used[i] = false;

for (int i = 0; i < N - 1; i++)

{

int x = 0;

for (int j = 0; (j + 1) != a[i]; j++) //до позиции данного числа в массиве

if (!used[j]) x++; //считаем неиспользованные числа

k += x * Factorials[N - 2 - i];

used[a[i] - 1] = true; //помечаем число как использованное

}

k++;

textBox6.Text = k.ToString();

}

//если ввод неправильный

else

{

textBox5.Text = "";

var result = MessageBox.Show("Перестановка - массив уникальных чисел от 1 до N, введенных через пробел в произвольном порядке",

"Ошибка ввода перестановки",

MessageBoxButtons.OK,

MessageBoxIcon.Error);

}

}

//----------------------------------------Clean All

Рисунок 2 – Итог работы программы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]