C/C++

Функция на рекурсию. Нужен код на С

Есть задача на рекурсию:
В течение сессии студенты сдают 4 экзамена, из которых 2 - по математике.
Сколькими способами можно составить расписание так, чтобы экзамены по математике не стояли рядом?
В задаче НЕТ рекурсии. Всего существует 4! = 24 варианта расписания. При этом существует всего 3 позиции, в которых 2 экзамена по математике стоят рядом: 1-2, 2-3, 3-4. Сами экзамены по математике в каждой из этих позиций можно разместить 2 разными способами, при этом остальные экзамены для каждой позиции также можно разместить 2 способами. Таким образом, всего существует 3 * 2 * 2 = 12 запрещённых вариантов расписания.

Ответ: 24 - 12 = 12 способов.

P.S. Программирование - это умение найти оптимальный способ решения задачи.

P.P.S. Но если тебе так хочется рекурсией, то:

int count(int s, int p) {
if (s == 0xF) { return 1; }
int res = 0;
for (int i = 1; i < 0x10; i <<= 1) {
if (!(i & s) && (i | p) != 3) { res += count(i | s, i); }
}
return res;
}

int main() {
printf("%d", count(0, 0x100));
}

Пусть код каждого экзамена - степень двойки: 1, 2, 4, 8.
Предположим, экзамены по математики имеют коды 1 и 2. Тогда достаточно проверить, что битовое сложение кодов предыдущего (p) и текущего (i) экзаменов не равно 3.
Чтобы пропустить экзамены, которые уже прошли, используется битовая маска s - битовое сложение кодов всех прошедших экзаменов. Если s == 0xF, значит все 4 экзамена состоялись.
Сергей Титоров
Сергей Титоров
52 312
Лучший ответ