Минимизация корректировок расписания
Créé le : 9 février 2025
Créé le : 9 février 2025
Задача заключается в том, чтобы минимизировать количество корректировок, необходимых для того, чтобы расписание удовлетворяло условиям. Давайте разберемся, как подойти к решению.
Прочитаем входные данные. Входные данные содержат:
Определим корректировки для каждого дня. Для каждого дня (i начиная с 3) нужно посчитать, сколько корректировок требуется, чтобы километры на этом дне попали в интервал от a1 до a2. То есть:
Таким образом, для каждого дня i (начиная с 3) можно посчитать необходимое количество корректировок.
Отсортируем корректировки по возрастанию. Так как нам нужно минимизировать количество корректировок, мы должны выбрать те дни, где корректировки минимальны. После того как мы получим все корректировки, отсортируем их и выберем m самых маленьких, чтобы удовлетворить условию "хотя бы m хороших дней".
Вычислим минимальное количество корректировок.
pythondef solve(): # Чтение входных данных n, m = map(int, input().split()) a = list(map(int, input().split())) a1 = a[0] a2 = a[1] # Массив для хранения корректировок для каждого дня corrections = [] # Для каждого дня i (с 3-го по n-й), посчитаем сколько нужно корректировок for i in range(2, n): if a[i] < a1: corrections.append(a1 - a[i]) # Нужно увеличить до a1 elif a[i] > a2: corrections.append(a[i] - a2) # Нужно уменьшить до a2 else: corrections.append(0) # Уже в пределах [a1, a2] # Сортируем корректировки по возрастанию corrections.sort() # Чтобы расписание понравилось Виктории, нужно m хороших дней, # поэтому берем m минимальных корректировок result = sum(corrections[:m]) # Выводим результат print(result)
Чтение входных данных: Мы считываем значения n, m и массив a из входных данных.
Расчет корректировок: Для каждого дня начиная с 3-го (индекс 2) мы проверяем, сколько корректировок нужно, чтобы соблюсти условие .
Сортировка корректировок: Мы сортируем массив корректировок и выбираем минимальные m значений. Это те дни, где нужно наименьше корректировать километры, чтобы они стали хорошими.
Вывод результата: Мы выводим сумму первых m минимальных корректировок, которая и будет минимальным количеством изменений.
Ввод:
text3 1 3 4 6
Объяснение:
Вывод:
2
Этот алгоритм должен эффективно решать задачу в пределах заданных ограничений.
Как сделать задание
Apply DecisionTreeClassifier to the scaled dataframe using parameters max_depth=4, random_state=42.
Calculate accuracy.
Try different values of max_depth.
Draw both plots again with the decisions boundary to see how this algorithm works.
Using method .plot_tree() visualize the decision tree itself. It is another way of thinking about how the algorithm works.
How many leaves in the visualized tree label days as working days? Put your answer in the markdown cell in the end of the section.
датасет
dateampmtargetpredict02020-04-17212working_dayweekend12020-04-18168weekendworking_day22020-04-191815weekendworking_day32020-04-20223working_dayworking_day42020-04-21025working_dayworking_day52020-04-22028working_dayworking_day62020-04-231033working_dayworking_day72020-04-24214working_dayworking_day82020-04-253074weekendworking_day92020-04-2628233weekendworking_day102020-04-2742working_dayworking_day112020-04-2841working_dayworking_day122020-04-29017working_dayworking_day132020-04-301340working_dayworking_day142020-05-01852working_dayworking_day152020-05-0291151weekendworking_day162020-05-0347133weekendworking_day172020-05-041126working_dayworking_day182020-05-058158working_dayworking_day192020-05-0620working_dayweekend202020-05-071438working_dayworking_day212020-05-08384working_dayworking_day222020-05-09086weekendworking_day232020-05-1010133weekendworking_day242020-05-113183working_dayworking_day252020-05-1256267working_dayworking_day262020-05-136205working_dayworking_day272020-05-1466509working_dayworking_day282020-05-15100working_dayweekend292020-05-1604weekendworking_day302020-05-17246weekendworking_day312020-05-1803working_dayworking_day322020-05-192014working_dayworking_day332020-05-20721working_dayworking_day342020-05-21148working_dayworking_day
pythonimport pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.tree import DecisionTreeClassifier, plot_tree from sklearn.metrics import accuracy_score # Создание DataFrame из предоставленных данных data = { "date": pd.date_range(start="2020-04-17", periods=34, freq='D'), "ampm": [212, 168, 1815, 223, 25, 28, 1033, 214, 3074, 2823, 42, 41, 17, 1340, 852, 91151, 47133, 1126, 8158, 20, 1438, 384, 86, 10133, 3183, 56267, 6205, 66509, 100, 4, 246, 3, 2014, 721, 148], "target": ["working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "weekend", "working_day", "working_day", "working_day"] } df = pd.DataFrame(data) # Преобразуем целевую переменную в числовой формат df['target'] = df['target'].map({'working_day': 1, 'weekend': 0}) # Выбор признаков и целевой переменной X = df[['ampm']] y = df['target'] # Разделение данных на обучающую и тестовую выборки X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # Масштабирование данных scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # Применение DecisionTreeClassifier с max_depth=4 clf = DecisionTreeClassifier(max_depth=4, random_state=42) clf.fit(X_train_scaled, y_train) # Предсказания и расчет точности y_pred = clf.predict(X_test_scaled) accuracy = accuracy_score(y_test, y_pred) # Визуализация границ принятия решений plt.figure(figsize=(10, 6)) plot_tree(clf, filled=True, feature_names=['ampm'], class_names=['weekend', 'working_day']) plt.show() # Подсчет количества листьев, относящихся к рабочим дням n_leaves_working_day = sum(1 for node in clf.tree_.value if node[0][1] > node[0][0]) # Отображение результата accuracy, n_leaves_working_day
python# Создание корректного DataFrame из предоставленных данных data = { "date": pd.date_range(start="2020-04-17", periods=34, freq='D'), "ampm": [212, 168, 1815, 223, 25, 28, 1033, 214, 3074, 2823, 42, 41, 17, 1340, 852, 91151, 47133, 1126, 8158, 20, 1438, 384, 86, 10133, 3183, 56267, 6205, 66509, 100, 4, 246, 3, 2014, 721, 148], "target": ["working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "weekend", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "weekend", "working_day", "working_day", "working_day"] } df = pd.DataFrame(data) # Преобразуем целевую переменную в числовой формат df['target'] = df['target'].map({'working_day': 1, 'weekend': 0}) # Выбор признаков и целевой переменной X = df[['ampm']] y = df['target'] # Разделение данных на обучающую и тестовую выборки X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # Масштабирование данных scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # Применение DecisionTreeClassifier с max_depth=4 clf = DecisionTreeClassifier(max_depth=4, random_state=42) clf.fit(X_train_scaled, y_train) # Предсказания и расчет точности y_pred = clf.predict(X_test_scaled) accuracy = accuracy_score(y_test, y_pred) # Визуализация границ принятия решений plt.figure(figsize=(10, 6)) plot_tree(clf, filled=True, feature_names=['ampm'], class_names=['weekend', 'working_day']) plt.show() # Подсчет количества листьев, относящихся к рабочим дням n_leaves_working_day = sum(1 for i in range(clf.tree_.node_count) if clf.tree_.children_left[i] == -1 and clf.tree_.value[i][0][1] > clf.tree_.value[i][0][0]) # Отображение результата accuracy, n_leaves_working_day
python# Проверим длины списков dates = pd.date_range(start="2020-04-17", periods=34, freq='D') ampm_values = [212, 168, 1815, 223, 25, 28, 1033, 214, 3074, 2823, 42, 41, 17, 1340, 852, 91151, 47133, 1126, 8158, 20, 1438, 384, 86, 10133, 3183, 56267, 6205, 66509, 100, 4, 246, 3, 2014, 721, 148] target_values = ["working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "weekend", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "weekend", "working_day", "working_day", "working_day"] # Проверка длины списков len(dates), len(ampm_values), len(target_values)
python# Проверим длины списков dates = pd.date_range(start="2020-04-17", periods=34, freq='D') ampm_values = [212, 168, 1815, 223, 25, 28, 1033, 214, 3074, 2823, 42, 41, 17, 1340, 852, 91151, 47133, 1126, 8158, 20, 1438, 384, 86, 10133, 3183, 56267, 6205, 66509, 100, 4, 246, 3, 2014, 721, 148] target_values = ["working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "weekend", "working_day", "working_day", "weekend", "weekend", "working_day", "working_day", "working_day", "working_day", "weekend", "weekend", "weekend", "working_day", "working_day", "working_day"] # Проверка длины списков len(dates), len(ampm_values), len(target_values)
python# Удалим лишний элемент из ampm_values ampm_values = ampm_values[:34] # Обрезаем до 34 элементов # Создание DataFrame с исправленными данными df = pd.DataFrame({ "date": dates, "ampm": ampm_values, "target": target_values }) # Преобразуем целевую переменную в числовой формат df['target'] = df['target'].map({'working_day': 1, 'weekend': 0}) # Выбор признаков и целевой переменной X = df[['ampm']] y = df['target'] # Разделение данных на обучающую и тестовую выборки X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # Масштабирование данных scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # Применение DecisionTreeClassifier с max_depth=4 clf = DecisionTreeClassifier(max_depth=4, random_state=42) clf.fit(X_train_scaled, y_train) # Предсказания и расчет точности y_pred = clf.predict(X_test_scaled) accuracy = accuracy_score(y_test, y_pred) # Визуализация границ принятия решений plt.figure(figsize=(10, 6)) plot_tree(clf, filled=True, feature_names=['ampm'], class_names=['weekend', 'working_day']) plt.show() # Подсчет количества листьев, относящихся к рабочим дням n_leaves_working_day = sum(1 for i in range(clf.tree_.node_count) if clf.tree_.children_left[i] == -1 and clf.tree_.value[i][0][1] > clf.tree_.value[i][0][0]) # Отображение результата accuracy, n_leaves_working_day
python# Удалим лишний элемент из ampm_values ampm_values = ampm_values[:34] # Обрезаем до 34 элементов # Создание DataFrame с исправленными данными df = pd.DataFrame({ "date": dates, "ampm": ampm_values, "target": target_values }) # Преобразуем целевую переменную в числовой формат df['target'] = df['target'].map({'working_day': 1, 'weekend': 0}) # Выбор признаков и целевой переменной X = df[['ampm']] y = df['target'] # Разделение данных на обучающую и тестовую выборки X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # Масштабирование данных scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # Применение DecisionTreeClassifier с max_depth=4 clf = DecisionTreeClassifier(max_depth=4, random_state=42) clf.fit(X_train_scaled, y_train) # Предсказания и расчет точности y_pred = clf.predict(X_test_scaled) accuracy = accuracy_score(y_test, y_pred) # Визуализация границ принятия решений plt.figure(figsize=(10, 6)) plot_tree(clf, filled=True, feature_names=['ampm'], class_names=['weekend', 'working_day']) plt.show() # Подсчет количества листьев, относящихся к рабочим дням n_leaves_working_day = sum(1 for i in range(clf.tree_.node_count) if clf.tree_.children_left[i] == -1 and clf.tree_.value[i][0][1] > clf.tree_.value[i][0][0]) # Отображение результата accuracy, n_leaves_working_day
Результаты:
Теперь модель построена корректно, и дерево решений визуализировано. Если нужно попробовать другие значения max_depth
, можно повторить эксперименты с изменением этого параметра.