Перебор всех вариантов

помогите пожалуйста решить задачу:

Мне нужно создать алгоритм, который будет находить подходящее расписания для школы ( у нас есть определенное количество классов с разными уроками, которые нужно провести за 6 дней обучения, для каждого урока есть свой учитель, свои ограничения (например, большинство уроков нужно размещать не больше раза в день, некоторые уроки нужно проводить в субботу и т.д.).

Я не прошу решить за меня, просто может подскажете, какой принцип можно для этого использовать, что почитать и т.д.

З.Ы. Был вот такой вот алгоритм, но чем дальше пишу программу, тем больше минусов в нём нахожу

private void generate_Click(object sender, RoutedEventArgs e)
        {

bool tooMuchLessons = false; string tooMuchLessonsFormName = ""; bool tooMuchLessonsToTeach = false; string tooMuchLessonsToTeachName = ""; // переменные, содержащие информацию о превышении лимита уроков для учителя/класса в неделю r.Next(); List<L> startLesson = new List<L>(); // список, в котором хранятся данные о первом уроке для перебора List<int> startLessonF = new List<int>(); // список, в котором хранятся данные о первок уроке для перебора ( он не изменяется в будущем ) int[] backs = new int[forms.Count]; foreach(Form form in forms) { int k = 0; foreach (Lesson lesson in form.lessons) k += lesson.amount; if(k > Form.MaxLessonsAmount) { tooMuchLessons = true; tooMuchLessonsFormName = form.number.ToString() + " \"" + form.letter.ToString() + "\""; } // проверили превышение лимита уроков для класса в неделю L temp = new L(r.Next(0, form.lessons.Count - 1), form.lessons.Count - 1); startLesson.Add(temp); startLessonF.Add(temp.GetValue()); // для каждого класса задан случайный первый урок и это значение сохранено } foreach (Teacher teacher in teachers) { int k = 0; foreach (Form form in forms) foreach (Lesson lesson in form.lessons) if (lesson.teach.fullname == teacher.fullname) k += lesson.amount; if (k > Teacher.MaxLessonsAmount) { tooMuchLessonsToTeach = true; tooMuchLessonsToTeachName = teacher.fullname; } } // проверяет превышение лимита уроков для учителя в неделю if(!tooMuchLessons && !tooMuchLessonsToTeach) // если не превышен лимит уроков для класса/учителя, то начинается перебор расписаний { schedules = new List<Schedule>(); // Расписания полностью обнуляются tschedules = new List<tSchedule>(); // Учительские расписания полностью обнуляются foreach (Form form in forms) schedules.Add(new Schedule()); // Создаются расписания, соотвествующие каждому классу foreach (Teacher teacher in teachers) tschedules.Add(new tSchedule()); // Создаются расписания, соответствующие каждому учителю for (int f_id = 0; f_id < tschedules.Count; f_id++) { for (int d_id = 0; d_id < 6; d_id++) { for (int l_id = 0; l_id < 12; l_id++) { tschedules[f_id].days[d_id].lessons[l_id] = new tLesson("", ""); } } } for (int form = 0; form < forms.Count; form++) // Перебираем каждый отдельный класс { Lesson[] LSN = new Lesson[forms[form].lessons.Count]; forms[form].lessons.CopyTo(LSN); Lesson T; for (int i = 0; i < LSN.Count(); i++) for (int k = 0; k < LSN.Count(); k++) if (LSN[i].sub.toughness > LSN[k].sub.toughness) { T = LSN[i]; LSN[i] = LSN[k]; LSN[k] = T; } List<int> LessonsLeft; // Переменная, отвечающаяя за количество оставшихся на неделю определенных уроков int LessonsAtAll = -1; // Переменная, отвечающая за количество оставшихся на неделю ВСЕХ уроков L LESSON; // Мы создаем переменную для перебора возможных уроков L startLessonT = new L(startLesson[form].GetValue(), LSN.Count() - 1); // Создаем переменную, которая будет меняться в случае неудачных расписаний int shift = 0; // По стандарту задаем смещение на 0 int s = 0; int f = 0; if (forms[form].secondShift) shift = 6; // Если у класса вторая смена, то смещение на 6 if (shift == 0) { s = 0; f = 6; } else { s = 5; f = 11; } for (int day = 0; day < 6; day++) // Перебираем каждый день для чистки учительского расписания (удаляем только те уроки, которые ведут у этого класса) for (int lesson = 0; lesson < 12; lesson++) // Перебираем уроки for (int tsched = 0; tsched < tschedules.Count; tsched++) // Проверяем расписание каждого учителя if (tschedules[tsched].days[day].lessons[lesson].form != "" && tschedules[tsched].days[day].lessons[lesson].form == (forms[form].number.ToString() + forms[form].letter)) // Условия обнуления tschedules[tsched].days[day].lessons[lesson] = new tLesson("", ""); // Само обнуление bool formFailed = false; // Переменная = true, если расписание сгенерировать не удалось int backSave = -1; for (int weekImplementations = 0; weekImplementations < LSN.Count() && LessonsAtAll != 0; weekImplementations++) // Если сгенерировать расписание не удалось, то повторяем, пока не закончатся варианты { LessonsLeft = new List<int>(); // Обнуляем для правильного подсчета LessonsAtAll = 0; // Обнуляем для правильного подсчета LESSON = new L(startLessonT.GetValue(), LSN.Count() - 1); // Мы создаем переменную для перебора возможных уроков foreach (Lesson lesson in LSN) { LessonsLeft.Add(lesson.amount); // Вводим значения количества определенных уроков на неделю LessonsAtAll += lesson.amount; // Вводим значения количество ВСЕХ уроков на неделю } //MessageBox.Show(LessonsAtAll.ToString()); foreach(int day in days) // Перебираем каждый отдельный день { List<int> LessonsADayLeft = new List<int>(); // Переменная, отвечающая за количество оставшихся на день определенных уроков foreach (Lesson lesson in LSN) LessonsADayLeft.Add(lesson.aday); // Вводим значения количества определенных уроков на день for (int lesson = 0; lesson < 12; lesson++) schedules[form].days[day].lessons[lesson] = new Lesson(0, 0, new Subject("", 0), new Teacher(" ", " ", " ", null), false, false); // Предварительно заполняем классное расписание пустыми уроками for (int lesson = s; lesson <= f; lesson++) // Перебираем каждый отдельный урок (первый равен смещению, последний равен 6 + смещение (чтобы уроки размещались на нужной смене) { bool DoubleCheck = false; foreach (Lesson l1 in schedules[form].days[day].lessons) foreach (Lesson l2 in schedules[form].days[day].lessons) if (l1 == l2) DoubleCheck = true; bool passedSaturdayCheck = (LSN[LESSON.GetValue()].saturday == (day == 5)); // Субботняя проверка bool passedAdditionalCheck = (LSN[LESSON.GetValue()].additional == ((lesson == 6 && shift == 0) || (lesson == 5 && shift == 6))); //MessageBox.Show(passedAdditionalCheck.ToString()); bool teacherUnavailable = (tschedules[teachers.IndexOf(LSN[LESSON.GetValue()].teach)].days[day].lessons[lesson].form != ""); // Проверяем, свободен ли учитель int implementations = LSN.Count(); // Количество попыток на установление урока bool passedDoubleCheck = (DoubleCheck && LSN[LESSON.GetValue()].aday == 2 && LessonsADayLeft[LESSON.GetValue()] == 1); while ((passedDoubleCheck || !passedSaturdayCheck || !passedAdditionalCheck || teacherUnavailable || LessonsLeft[LESSON.GetValue()] == 0 || LessonsADayLeft[LESSON.GetValue()] == 0) && implementations > 0) { LESSON.inc(); // Если урок не подходит по какому-то из параметров, то мы меняем урок, который хотим поставить passedSaturdayCheck = (LSN[LESSON.GetValue()].saturday == (day == 5)); // Субботняя проверка, после обновления passedAdditionalCheck = (LSN[LESSON.GetValue()].additional == ((lesson == 6 && shift == 0) || (lesson == 5 && shift == 6))); passedDoubleCheck = (DoubleCheck && LSN[LESSON.GetValue()].aday == 2 && LessonsADayLeft[LESSON.GetValue()] == 0); teacherUnavailable = (tschedules[teachers.IndexOf(LSN[LESSON.GetValue()].teach)].days[day].lessons[lesson].form != ""); // Проверяем, свободен ли учитель после обновления implementations--; // Уменьшаем количество оставшихся попыток } if (implementations == 0) schedules[form].days[day].lessons[lesson] = new Lesson(0, 0, new Subject(" ", 0), new Teacher(" ", " ", " ", null), false, false); // Если попытки закончились, то устаналвиваем пропускной урок else // А если мы нашли подходящий урок, то { schedules[form].days[day].lessons[lesson] = LSN[LESSON.GetValue()]; // Устанавливаем найденный урок LessonsADayLeft[LESSON.GetValue()]--; LessonsLeft[LESSON.GetValue()]--; // Уменьшаем количество оставшихся уроков в день и в неделю LessonsAtAll--; // Уменьшаем количество уроков, которые все ещё нужно куда-то установить } } // Конец цикла перебора уроков } // Конец цикла перебора //MessageBox.Show(LessonsAtAll.ToString()); startLessonT.inc(); // Меняем первый урок на случай, если расписание не сгенерировалось и мы снова идем по кругу } startLesson[form].inc(); // Меняем стартовый урок для класса на случай возвращения сюда if (LessonsAtAll != 0) { formFailed = true; } // Если не все уроки установлены в расписании, то нам не удалось его сгенерировать if ((backs[0] == LSN.Count() || forms.Count == 1) && formFailed == true) { FAILED = true; break; } // Если первый класс перегенерировался уже максимальное количество раз, то прекращаем пытаться' int tempHowBack = 0; // Создаем переменную для возвращения if(form > 0) for (tempHowBack = 1; (form - tempHowBack >= 0 && backs[form - tempHowBack] == LSN.Count()); tempHowBack++) ; // Определяем как сильно назад нам нужно вернуться if (backSave == form && !formFailed) for (int i = 0; i < backs.Count(); i++) backs[i] = 0; // Если нам удалось сгенерировать то очищаем количество возвращений if (form > 0 && formFailed) { backSave = form; form -= (1 + tempHowBack); backs[form+1]++;} // Если не удалось, то возвращаемся на класс назад и создаем ему другое расписание if (LessonsAtAll == 0) { formFailed = false; } // Если сгенерировалось, то не провалено лол if (!formFailed) // Если провалено { for (int day = 0; day < 6; day++) // Перебираем дни для записи в учительское расписание { for (int lesson = 0; lesson < 12; lesson++) // Перебираем уроки для записи в учительское расписание { if (schedules[form].days[day].lessons[lesson].teach.fullname != " ") // Если урок не пустой, то tschedules[teachers.IndexOf(schedules[form].days[day].lessons[lesson].teach)].days[day].lessons[lesson] = new tLesson(forms[form].fullname, schedules[form].days[day].lessons[lesson].sub.name); // Записали урок в учительское расписание } // Конец перебора уроков для учителей } // Конец перебора дней для учителей } formFailed = false; } // Конец цикла перебора классов } if (FAILED) this.ShowMessageAsync("Ошибка!", "Не удалось сгенерировать расписание с заданными условиями, попробуйте изменить их."); object save = FormsList.SelectedItem; FormsList.SelectedItem = null; FormsList.SelectedItem = save; }<code>

Ответы (0 шт):