Примеры
Здесь приведены задания и соответствующие им программы, все пояснения в коде.
Задания для самостоятельного выполнения
Пример 3
Р-10 (демо-2021). На рисунке справа схема дорог Н-ского района изображена в виде
графа, в таблице содержатся сведения о длинах этих дорог (в километрах).
Так как таблицу и схему рисовали независимо друг от друга, то нумерация населённых
пунктов в таблице никак не связана с буквенными обозначениями на графе. Определите,
какова протяжённость дороги из пункта Г в пункт Ж. В ответе запишите целое число –
так, как оно указано в таблице.
- Java
- C++
- Python
public class Example3 {
// кол-во вершин (используется для удобства)
static int SIZE = 7;
// названия вершин
static char[] names = {'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж'};
// П1 П2 П3 П4 П5 П6 П7
static int[][] source = new int[][]{
{0, 0, 0, 9, 0, 0, 7}, // П1
{0, 0, 0, 5, 0, 11, 0}, // П2
{0, 0, 0, 0, 0, 12, 0}, // П3
{9, 5, 0, 0, 4, 13, 15}, // П4
{0, 0, 0, 4, 0, 10, 8}, // П5
{0, 11, 12, 13, 10, 0, 0}, // П6
{7, 0, 0, 15, 8, 0, 0} // П7
};
// А Б В Г Д Е Ж
static int[][] target = new int[][]{
{0, 1, 0, 0, 0, 0, 0}, // A
{1, 0, 1, 0, 0, 1, 1}, // Б
{0, 1, 0, 0, 0, 0, 1}, // В
{0, 0, 0, 0, 1, 0, 1}, // Г
{0, 0, 0, 1, 0, 1, 1}, // Д
{0, 1, 0, 0, 1, 0, 1}, // Е
{0, 1, 1, 1, 1, 1, 0} // Ж
};
// степени вершин
static int[] sourceSum = new int[SIZE];
static int[] targetSum = new int[SIZE];
// получить обратную перестановку
static int[] getReversePermutation(int[] arr) {
int[] reverse = new int[arr.length];
for (int i = 0; i < SIZE; i++) {
reverse[arr[i]] = i;
}
return reverse;
}
// обработка перестановки
static void processPermutation(int[] arr) {
// проверяем, что в представлениях совпадают степени вершин
for (int i = 0; i < SIZE; i++) {
if (sourceSum[arr[i]] != targetSum[i]) {
return;
}
}
// нужна проверка связности, т.е. того, что при перестановке все связи сохраняются, те не
// обратятся в ноль
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
// если в эталонном представлении связь между вершинами есть,
// а в данном в задании - нет
if (target[i][j] > 0 && source[arr[i]][arr[j]] == 0)
// заканчиваем выполнение обработчика, потому такая перестановка
// создаёт представление, не совместимое с данным, а значит, нас не
// интересует
return;
}
}
// здесь мы уже выполняем проверку, определённую заданием
// получаем обратную перестановку
int[] reverse = getReversePermutation(arr);
// выводим названия вершин
for (int i = 0; i < SIZE; i++) {
System.out.print(names[reverse[i]] + " ");
}
System.out.println();
int gjDistance = source[arr[6]][arr[3]];
System.out.println(gjDistance);
}
// поменять местами элементы массива arr с индексами l и r
public static void swap(int[] arr, int l, int r) {
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
}
// функция-генератор перестановок
static void permute(int[] p, int pos) {
// Если мы дошли до последнего элемента
if (pos == SIZE - 1) {
processPermutation(p);
} else { // иначе
// Перебираем все оставшиеся элементы
for (int i = pos; i < SIZE; i++) {
// меняем местами текущий элемент и перебираемый
swap(p, pos, i);
// Вызываем Рекурсию для следующего элемента
permute(p, pos + 1);
// меняем местами обратно
swap(p, pos, i);
}
}
}
// главный метод программы
public static void main(String[] args) {
// рассчитываем взвешенные степени
for (int i = 0; i < SIZE; i++) {
sourceSum[i] = 0;
targetSum[i] = 0;
for (int j = 0; j < SIZE; j++) {
// в исходном представлении надо не забыть заменить ненулевые веса единицей
sourceSum[i] += Math.signum(source[i][j]);
targetSum[i] += target[i][j];
}
}
// запускаем генерацию перестановок
permute(new int[7]{0, 1, 2, 3, 4, 5, 6}, 0);
}
}
#include <iostream>
#include <bits/stdc++.h>
// кол-во вершин (используется для удобства)
const int SIZE = 7;
// П1 П2 П3 П4 П5 П6 П7
const int source[SIZE][SIZE] = {
{0, 0, 0, 9, 0, 0, 7}, // П1
{0, 0, 0, 5, 0, 11, 0}, // П2
{0, 0, 0, 0, 0, 12, 0}, // П3
{9, 5, 0, 0, 4, 13, 15}, // П4
{0, 0, 0, 4, 0, 10, 8}, // П5
{0, 11, 12, 13, 10, 0, 0}, // П6
{7, 0, 0, 15, 8, 0, 0} // П7
};
// А Б В Г Д Е Ж
const int target[SIZE][SIZE] = {
{0, 1, 0, 0, 0, 0, 0}, // A
{1, 0, 1, 0, 0, 1, 1}, // Б
{0, 1, 0, 0, 0, 0, 1}, // В
{0, 0, 0, 0, 1, 0, 1}, // Г
{0, 0, 0, 1, 0, 1, 1}, // Д
{0, 1, 0, 0, 1, 0, 1}, // Е
{0, 1, 1, 1, 1, 1, 0} // Ж
};
// степени вершин
int sourceSum[SIZE];
int targetSum[SIZE];
// получить обратную перестановку
int *getReversePermutation(std::vector<int> arr) {
static int reverse[SIZE];
for (int i = 0; i < SIZE; i++) {
reverse[arr[i]] = i;
}
return reverse;
}
// обработка перестановки
void processPermutation(std::vector<int> arr) {
// проверяем, что в представлениях совпадают степени вершин
for (int i = 0; i < SIZE; i++) {
if (sourceSum[arr[i]] != targetSum[i]) {
return;
}
}
// нужна проверка связности, т.е. того, что при перестановке все связи сохраняются, те не
// обратятся в ноль
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
// если в эталонном представлении связь между вершинами есть,
// а в данном в задании - нет
if (target[i][j] > 0 && source[arr[i]][arr[j]] == 0)
// заканчиваем выполнение обработчика, потому такая перестановка
// создаёт представление, не совместимое с данным, а значит, нас не
// интересует
return;
}
}
// здесь мы уже выполняем проверку, определённую заданием
// получаем обратную перестановку
int *reverse = getReversePermutation(arr);
// названия вершин
const std::string names[SIZE] = {"A", "B", "C", "D", "E", "F", "G"};
// выводим названия вершин
for (int i = 0; i < SIZE; i++) {
std::cout << names[reverse[i]] << " ";
}
std::cout << std::endl;
// выводим расстояния
int gjDistance = source[arr[6]][arr[3]];
std::cout << gjDistance << std::endl;
}
// главный метод программы
int main() {
// рассчитываем взвешенные степени
for (int i = 0; i < SIZE; i++) {
sourceSum[i] = 0;
targetSum[i] = 0;
for (int j = 0; j < SIZE; j++) {
// в исходном представлении надо не забыть заменить ненулевые веса единицей
sourceSum[i] += source[i][j] > 0 ? 1 : 0;
targetSum[i] += target[i][j];
}
}
std::vector<int> origin = {0, 1, 2, 3, 4, 5, 6};
do {
processPermutation(origin);
} while (std::next_permutation(origin.begin(), origin.end()));
return 0;
}
import itertools
# кол-во вершин (используется для удобства)
SIZE = 7
# названия вершин
names = ['А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж']
# П1 П2 П3 П4 П5 П6 П7
source = [
[0, 0, 0, 9, 0, 0, 7], # П1
[0, 0, 0, 5, 0, 11, 0], # П2
[0, 0, 0, 0, 0, 12, 0], # П3
[9, 5, 0, 0, 4, 13, 15], # П4
[0, 0, 0, 4, 0, 10, 8], # П5
[0, 11, 12, 13, 10, 0, 0], # П6
[7, 0, 0, 15, 8, 0, 0] # П7
]
# А Б В Г Д Е Ж
target = [
[0, 1, 0, 0, 0, 0, 0], # A
[1, 0, 1, 0, 0, 1, 1], # Б
[0, 1, 0, 0, 0, 0, 1], # В
[0, 0, 0, 0, 1, 0, 1], # Г
[0, 0, 0, 1, 0, 1, 1], # Д
[0, 1, 0, 0, 1, 0, 1], # Е
[0, 1, 1, 1, 1, 1, 0] # Ж
]
# степени вершин
source_sum = [0 for i in range(SIZE)]
target_sum = [0 for i in range(SIZE)]
# получить обратную перестановку
def get_reverse_permutation(arr):
reverse = [0] * len(arr)
for i in range(len(arr)):
reverse[arr[i]] = i
return reverse
# обработка перестановки
def process_permutation(arr):
# проверяем, что в представлениях совпадают степени вершин
for i in range(SIZE):
if source_sum[arr[i]] != target_sum[i]:
return
# нужна проверка связности, т.е. того, что при перестановке все связи сохраняются, те не
# обратятся в ноль
for i in range(SIZE):
for j in range(SIZE):
# если в эталонном представлении связь между вершинами есть,
# а в данном в задании - нет
if target[i][j] > 0 and source[arr[i]][arr[j]] == 0:
# заканчиваем выполнение обработчика, потому такая перестановка
# создаёт представление, не совместимое с данным, а значит, нас не
# интересует
return
# здесь мы уже выполняем проверку, определённую заданием
# формируем заголовок
header = ""
# получаем обратную перестановку
reverse = get_reverse_permutation(arr)
for i in range(SIZE):
header += names[reverse[i]] + " "
# выводим названия вершин
print(header)
gjDistance = source[arr[6]][arr[3]]
print(gjDistance)
# главный метод программы
if __name__ == '__main__':
# рассчитываем взвешенные степени
for i in range(SIZE):
source_sum[i] = 0
target_sum[i] = 0
for j in range(SIZE):
# в исходном представлении надо не забыть заменить ненулевые веса единицей
source_sum[i] += 1 if source[i][j] > 0 else 0
target_sum[i] += target[i][j]
permutations = list(itertools.permutations([0, 1, 2, 3, 4, 5, 6]))
for permutation in permutations:
process_permutation(permutation)
На выходе получим:
Г В А Ж Е Б Д
9
Пример 4
На рисунке справа схема дорог Н-ского района изображена в виде графа, в таблице содержатся
сведения о длинах этих дорог (в километрах). Так как таблицу и схему рисовали независимо
друг от друга, то нумерация населённых пунктов в таблице никак не связана с буквенными
обозначениями на графе. Определите, какова длина дороги из пункта В в пункт Е.
В ответе запишите целое число – так, как оно указано в таблице.
- Java
- C++
- Python
public class Example4 {
// кол-во вершин (используется для удобства)
static int SIZE = 7;
// названия вершин
static char[] names = {'А', 'Б', 'В', 'Г', 'Д', 'Е', 'К'};
// П1 П2 П3 П4 П5 П6 П7
static int[][] source = new int[][]{
{0, 45, 0, 10, 0, 0, 0}, // П1
{45, 0, 0, 40, 0, 55, 0}, // П2
{0, 0, 0, 0,15, 60, 0}, // П3
{10, 40, 0, 0, 0, 20, 35}, // П4
{0, 0, 15, 0, 0, 55, 0}, // П5
{0, 55, 60, 20, 55, 0, 45}, // П6
{0, 0, 0, 35, 0, 45, 0} // П7
};
// А Б В Г Д Е К
static int[][] target = new int[][]{
{0, 1, 1, 0, 0, 0, 0}, // A
{1, 0, 1, 0, 0, 0, 0}, // Б
{1, 1, 0, 1, 1, 1, 0}, // В
{0, 0, 1, 0, 0, 1, 1}, // Г
{0, 0, 1, 0, 0, 1, 0}, // Д
{0, 0, 1, 1, 1, 0, 1}, // Е
{0, 0, 0, 1, 0, 1, 0} // К
};
// степени вершин
static int[] sourceSum = new int[SIZE];
static int[] targetSum = new int[SIZE];
// получить обратную перестановку
static int[] getReversePermutation(int[] arr) {
int[] reverse = new int[arr.length];
for (int i = 0; i < SIZE; i++) {
reverse[arr[i]] = i;
}
return reverse;
}
// обработка перестановки
static void processPermutation(int[] arr) {
// проверяем, что в представлениях совпадают степени вершин
for (int i = 0; i < SIZE; i++) {
if (sourceSum[arr[i]] != targetSum[i]) {
return;
}
}
// нужна проверка связности, т.е. того, что при перестановке все связи сохраняются, те не
// обратятся в ноль
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
// если в эталонном представлении связь между вершинами есть,
// а в данном в задании - нет
if (target[i][j] > 0 && source[arr[i]][arr[j]] == 0)
// заканчиваем выполнение обработчика, потому такая перестановка
// создаёт представление, не совместимое с данным, а значит, нас не
// интересует
return;
}
}
// здесь мы уже выполняем проверку, определённую заданием
// получаем обратную перестановку
int[] reverse = getReversePermutation(arr);
// выводим названия вершин
for (int i = 0; i < SIZE; i++) {
System.out.print(names[reverse[i]] + " ");
}
System.out.println();
int veDistance = source[arr[2]][arr[5]];
System.out.println(veDistance);
}
// поменять местами элементы массива arr с индексами l и r
public static void swap(int[] arr, int l, int r) {
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
}
// функция-генератор перестановок
static void permute(int[] p, int pos) {
// Если мы дошли до последнего элемента
if (pos == SIZE - 1) {
processPermutation(p);
} else { // иначе
// Перебираем все оставшиеся элементы
for (int i = pos; i < SIZE; i++) {
// меняем местами текущий элемент и перебираемый
swap(p, pos, i);
// Вызываем Рекурсию для следующего элемента
permute(p, pos + 1);
// меняем местами обратно
swap(p, pos, i);
}
}
}
// главный метод программы
public static void main(String[] args) {
// рассчитываем взвешенные степени
for (int i = 0; i < SIZE; i++) {
sourceSum[i] = 0;
targetSum[i] = 0;
for (int j = 0; j < SIZE; j++) {
// в исходном представлении надо не забыть заменить ненулевые веса единицей
sourceSum[i] += Math.signum(source[i][j]);
targetSum[i] += target[i][j];
}
}
// запускаем генерацию перестановок
permute(new int[]{0, 1, 2, 3, 4, 5, 6}, 0);
}
}
#include <iostream>
#include <bits/stdc++.h>
// кол-во вершин (используется для удобства)
const int SIZE = 7;
// П1 П2 П3 П4 П5 П6 П7
const int source[SIZE][SIZE] = {
{0, 45, 0, 10, 0, 0, 0}, // П1
{45, 0, 0, 40, 0, 55, 0}, // П2
{0, 0, 0, 0,15, 60, 0}, // П3
{10, 40, 0, 0, 0, 20, 35}, // П4
{0, 0, 15, 0, 0, 55, 0}, // П5
{0, 55, 60, 20, 55, 0, 45}, // П6
{0, 0, 0, 35, 0, 45, 0} // П7
};
// А Б В Г Д Е Ж
const int target[SIZE][SIZE] = {
{0, 1, 1, 0, 0, 0, 0}, // A
{1, 0, 1, 0, 0, 0, 0}, // Б
{1, 1, 0, 1, 1, 1, 0}, // В
{0, 0, 1, 0, 0, 1, 1}, // Г
{0, 0, 1, 0, 0, 1, 0}, // Д
{0, 0, 1, 1, 1, 0, 1}, // Е
{0, 0, 0, 1, 0, 1, 0} // К
};
// степени вершин
int sourceSum[SIZE];
int targetSum[SIZE];
// получить обратную перестановку
int *getReversePermutation(std::vector<int> arr) {
static int reverse[SIZE];
for (int i = 0; i < SIZE; i++) {
reverse[arr[i]] = i;
}
return reverse;
}
// обработка перестановки
void processPermutation(std::vector<int> arr) {
// проверяем, что в представлениях совпадают степени вершин
for (int i = 0; i < SIZE; i++) {
if (sourceSum[arr[i]] != targetSum[i]) {
return;
}
}
// нужна проверка связности, т.е. того, что при перестановке все связи сохраняются, те не
// обратятся в ноль
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
// если в эталонном представлении связь между вершинами есть,
// а в данном в задании - нет
if (target[i][j] > 0 && source[arr[i]][arr[j]] == 0)
// заканчиваем выполнение обработчика, потому такая перестановка
// создаёт представление, не совместимое с данным, а значит, нас не
// интересует
return;
}
}
// здесь мы уже выполняем проверку, определённую заданием
// получаем обратную перестановку
int *reverse = getReversePermutation(arr);
// названия вершин
const std::string names[SIZE] = {"A", "B", "C", "D", "E", "F", "G"};
// выводим названия вершин
for (int i = 0; i < SIZE; i++) {
std::cout << names[reverse[i]] << " ";
}
std::cout << std::endl;
// выводим расстояния
int veDistance = source[arr[2]][arr[5]];
std::cout << veDistance << std::endl;
}
// главный метод программы
int main() {
// рассчитываем взвешенные степени
for (int i = 0; i < SIZE; i++) {
sourceSum[i] = 0;
targetSum[i] = 0;
for (int j = 0; j < SIZE; j++) {
// в исходном представлении надо не забыть заменить ненулевые веса единицей
sourceSum[i] += source[i][j] > 0 ? 1 : 0;
targetSum[i] += target[i][j];
}
}
std::vector<int> origin = {0, 1, 2, 3, 4, 5, 6};
do {
processPermutation(origin);
} while (std::next_permutation(origin.begin(), origin.end()));
return 0;
}
import itertools
# кол-во вершин (используется для удобства)
SIZE = 7
# названия вершин
names = ['А', 'Б', 'В', 'Г', 'Д', 'Е', 'К']
# П1 П2 П3 П4 П5 П6 П7
source = [
[0, 45, 0, 10, 0, 0, 0], # П1
[45, 0, 0, 40, 0, 55, 0], # П2
[0, 0, 0, 0,15, 60, 0], # П3
[10, 40, 0, 0, 0, 20, 35], # П4
[0, 0, 15, 0, 0, 55, 0], # П5
[0, 55, 60, 20, 55, 0, 45], # П6
[0, 0, 0, 35, 0, 45, 0] # П7
]
# А Б В Г Д Е К
target = [
[0, 1, 1, 0, 0, 0, 0], # A
[1, 0, 1, 0, 0, 0, 0], # Б
[1, 1, 0, 1, 1, 1, 0], # В
[0, 0, 1, 0, 0, 1, 1], # Г
[0, 0, 1, 0, 0, 1, 0], # Д
[0, 0, 1, 1, 1, 0, 1], # Е
[0, 0, 0, 1, 0, 1, 0] # К
]
# степени вершин
source_sum = [0 for i in range(SIZE)]
target_sum = [0 for i in range(SIZE)]
# получить обратную перестановку
def get_reverse_permutation(arr):
reverse = [0] * len(arr)
for i in range(len(arr)):
reverse[arr[i]] = i
return reverse
# обработка перестановки
def process_permutation(arr):
# проверяем, что в представлениях совпадают степени вершин
for i in range(SIZE):
if source_sum[arr[i]] != target_sum[i]:
return
# нужна проверка связности, т.е. того, что при перестановке все связи сохраняются, те не
# обратятся в ноль
for i in range(SIZE):
for j in range(SIZE):
# если в эталонном представлении связь между вершинами есть,
# а в данном в задании - нет
if target[i][j] > 0 and source[arr[i]][arr[j]] == 0:
# заканчиваем выполнение обработчика, потому такая перестановка
# создаёт представление, не совместимое с данным, а значит, нас не
# интересует
return
# здесь мы уже выполняем проверку, определённую заданием
# формируем заголовок
header = ""
# получаем обратную перестановку
reverse = get_reverse_permutation(arr)
for i in range(SIZE):
header += names[reverse[i]] + " "
# выводим названия вершин
print(header)
veDistance = source[arr[2]][arr[5]]
print(veDistance)
# главный метод программы
if __name__ == '__main__':
# рассчитываем взвешенные степени
for i in range(SIZE):
source_sum[i] = 0
target_sum[i] = 0
for j in range(SIZE):
# в исходном представлении надо не забыть заменить ненулевые веса единицей
source_sum[i] += 1 if source[i][j] > 0 else 0
target_sum[i] += target[i][j]
permutations = list(itertools.permutations([0, 1, 2, 3, 4, 5, 6]))
for permutation in permutations:
process_permutation(permutation)
На выходе получим:
К Г А Е Б В Д
20
К Г Б Е А В Д
20
Пример 5
На рисунке справа схема дорог Н-ского района изображена в виде графа, в таблице содержатся
сведения о длинах этих дорог (в километрах). Так как таблицу и схему рисовали независимо друг
от друга, то нумерация населённых пунктов в таблице никак не связана с буквенными
обозначениями на графе. Определите, какова длина дороги из пункта А в пункт Д. В ответе
запишите целое число – так, как оно указано в таблице.
- Java
- C++
- Python
public class Example5 {
// кол-во вершин (используется для удобства)
static int SIZE = 7;
// названия вершин
static char[] names = {'А', 'Б', 'В', 'Г', 'Д', 'Е', 'К'};
// П1 П2 П3 П4 П5 П6 П7
static int[][] source = new int[][]{
{0, 0, 30, 0, 25, 0, 18}, // П1
{0, 0, 17, 12, 0, 0, 0}, // П2
{30, 17, 0, 23,0, 34, 15}, // П3
{0, 12, 23, 0, 0, 46, 0}, // П4
{25, 0, 0, 0, 0, 0, 37}, // П5
{0, 0, 34, 46, 0, 0, 18}, // П6
{18, 0, 15, 0, 37, 18, 0} // П7
};
// А Б В Г Д Е К
static int[][] target = new int[][]{
{0, 1, 1, 0, 1, 0, 0}, // A
{1, 0, 1, 0, 0, 0, 0}, // Б
{1, 1, 0, 1, 1, 1, 0}, // В
{0, 0, 1, 0, 0, 1, 1}, // Г
{1, 0, 1, 0, 0, 1, 0}, // Д
{0, 0, 1, 1, 1, 0, 1}, // Е
{0, 0, 0, 1, 0, 1, 0} // К
};
// степени вершин
static int[] sourceSum = new int[SIZE];
static int[] targetSum = new int[SIZE];
// получить обратную перестановку
static int[] getReversePermutation(int[] arr) {
int[] reverse = new int[arr.length];
for (int i = 0; i < SIZE; i++) {
reverse[arr[i]] = i;
}
return reverse;
}
// обработка перестановки
static void processPermutation(int[] arr) {
// проверяем, что в представлениях совпадают степени вершин
for (int i = 0; i < SIZE; i++) {
if (sourceSum[arr[i]] != targetSum[i]) {
return;
}
}
// нужна проверка связности, т.е. того, что при перестановке все связи сохраняются, те не
// обратятся в ноль
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
// если в эталонном представлении связь между вершинами есть,
// а в данном в задании - нет
if (target[i][j] > 0 && source[arr[i]][arr[j]] == 0)
// заканчиваем выполнение обработчика, потому такая перестановка
// создаёт представление, не совместимое с данным, а значит, нас не
// интересует
return;
}
}
// здесь мы уже выполняем проверку, определённую заданием
// получаем обратную перестановку
int[] reverse = getReversePermutation(arr);
// выводим названия вершин
for (int i = 0; i < SIZE; i++) {
System.out.print(names[reverse[i]] + " ");
}
System.out.println();
int adDistance = source[arr[0]][arr[4]];
System.out.println(adDistance);
}
// поменять местами элементы массива arr с индексами l и r
public static void swap(int[] arr, int l, int r) {
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
}
// функция-генератор перестановок
static void permute(int[] p, int pos) {
// Если мы дошли до последнего элемента
if (pos == SIZE - 1) {
processPermutation(p);
} else { // иначе
// Перебираем все оставшиеся элементы
for (int i = pos; i < SIZE; i++) {
// меняем местами текущий элемент и перебираемый
swap(p, pos, i);
// Вызываем Рекурсию для следующего элемента
permute(p, pos + 1);
// меняем местами обратно
swap(p, pos, i);
}
}
}
// главный метод программы
public static void main(String[] args) {
// рассчитываем взвешенные степени
for (int i = 0; i < SIZE; i++) {
sourceSum[i] = 0;
targetSum[i] = 0;
for (int j = 0; j < SIZE; j++) {
// в исходном представлении надо не забыть заменить ненулевые веса единицей
sourceSum[i] += Math.signum(source[i][j]);
targetSum[i] += target[i][j];
}
}
// запускаем генерацию перестановок
permute(new int[]{0, 1, 2, 3, 4, 5, 6}, 0);
}
}
#include <iostream>
#include <bits/stdc++.h>
// кол-во вершин (используется для удобства)
const int SIZE = 7;
// П1 П2 П3 П4 П5 П6 П7
const int source[SIZE][SIZE] = {
{0, 0, 30, 0, 25, 0, 18}, // П1
{0, 0, 17, 12, 0, 0, 0}, // П2
{30, 17, 0, 23,0, 34, 15}, // П3
{0, 12, 23, 0, 0, 46, 0}, // П4
{25, 0, 0, 0, 0, 0, 37}, // П5
{0, 0, 34, 46, 0, 0, 18}, // П6
{18, 0, 15, 0, 37, 18, 0} // П7
};
// А Б В Г Д Е Ж
const int target[SIZE][SIZE] = {
{0, 1, 1, 0, 1, 0, 0}, // A
{1, 0, 1, 0, 0, 0, 0}, // Б
{1, 1, 0, 1, 1, 1, 0}, // В
{0, 0, 1, 0, 0, 1, 1}, // Г
{1, 0, 1, 0, 0, 1, 0}, // Д
{0, 0, 1, 1, 1, 0, 1}, // Е
{0, 0, 0, 1, 0, 1, 0} // К
};
// степени вершин
int sourceSum[SIZE];
int targetSum[SIZE];
// получить обратную перестановку
int *getReversePermutation(std::vector<int> arr) {
static int reverse[SIZE];
for (int i = 0; i < SIZE; i++) {
reverse[arr[i]] = i;
}
return reverse;
}
// обработка перестановки
void processPermutation(std::vector<int> arr) {
// проверяем, что в представлениях совпадают степени вершин
for (int i = 0; i < SIZE; i++) {
if (sourceSum[arr[i]] != targetSum[i]) {
return;
}
}
// нужна проверка связности, т.е. того, что при перестановке все связи сохраняются, те не
// обратятся в ноль
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
// если в эталонном представлении связь между вершинами есть,
// а в данном в задании - нет
if (target[i][j] > 0 && source[arr[i]][arr[j]] == 0)
// заканчиваем выполнение обработчика, потому такая перестановка
// создаёт представление, не совместимое с данным, а значит, нас не
// интересует
return;
}
}
// здесь мы уже выполняем проверку, определённую заданием
// получаем обратную перестановку
int *reverse = getReversePermutation(arr);
// названия вершин
const std::string names[SIZE] = {"A", "B", "C", "D", "E", "F", "G"};
// выводим названия вершин
for (int i = 0; i < SIZE; i++) {
std::cout << names[reverse[i]] << " ";
}
std::cout << std::endl;
// выводим расстояния
int adDistance = source[arr[0]][arr[4]];
std::cout << adDistance << std::endl;
}
// главный метод программы
int main() {
// рассчитываем взвешенные степени
for (int i = 0; i < SIZE; i++) {
sourceSum[i] = 0;
targetSum[i] = 0;
for (int j = 0; j < SIZE; j++) {
// в исходном представлении надо не забыть заменить ненулевые веса единицей
sourceSum[i] += source[i][j] > 0 ? 1 : 0;
targetSum[i] += target[i][j];
}
}
std::vector<int> origin = {0, 1, 2, 3, 4, 5, 6};
do {
processPermutation(origin);
} while (std::next_permutation(origin.begin(), origin.end()));
return 0;
}
import itertools
# кол-во вершин (используется для удобства)
SIZE = 7
# названия вершин
names = ['А', 'Б', 'В', 'Г', 'Д', 'Е', 'К']
# П1 П2 П3 П4 П5 П6 П7
source = [
[0, 0, 30, 0, 25, 0, 18], # П1
[0, 0, 17, 12, 0, 0, 0], # П2
[30, 17, 0, 23,0, 34, 15], # П3
[0, 12, 23, 0, 0, 46, 0], # П4
[25, 0, 0, 0, 0, 0, 37], # П5
[0, 0, 34, 46, 0, 0, 18], # П6
[18, 0, 15, 0, 37, 18, 0] # П7
]
# А Б В Г Д Е К
target = [
[0, 1, 1, 0, 1, 0, 0], # A
[1, 0, 1, 0, 0, 0, 0], # Б
[1, 1, 0, 1, 1, 1, 0], # В
[0, 0, 1, 0, 0, 1, 1], # Г
[1, 0, 1, 0, 0, 1, 0], # Д
[0, 0, 1, 1, 1, 0, 1], # Е
[0, 0, 0, 1, 0, 1, 0] # К
]
# степени вершин
source_sum = [0 for i in range(SIZE)]
target_sum = [0 for i in range(SIZE)]
# получить обратную перестановку
def get_reverse_permutation(arr):
reverse = [0] * len(arr)
for i in range(len(arr)):
reverse[arr[i]] = i
return reverse
# обработка перестановки
def process_permutation(arr):
# проверяем, что в представлениях совпадают степени вершин
for i in range(SIZE):
if source_sum[arr[i]] != target_sum[i]:
return
# нужна проверка связности, т.е. того, что при перестановке все связи сохраняются, те не
# обратятся в ноль
for i in range(SIZE):
for j in range(SIZE):
# если в эталонном представлении связь между вершинами есть,
# а в данном в задании - нет
if target[i][j] > 0 and source[arr[i]][arr[j]] == 0:
# заканчиваем выполнение обработчика, потому такая перестановка
# создаёт представление, не совместимое с данным, а значит, нас не
# интересует
return
# здесь мы уже выполняем проверку, определённую заданием
# формируем заголовок
header = ""
# получаем обратную перестановку
reverse = get_reverse_permutation(arr)
for i in range(SIZE):
header += names[reverse[i]] + " "
# выводим названия вершин
print(header)
adDistance = source[arr[0]][arr[4]]
print(adDistance)
# главный метод программы
if __name__ == '__main__':
# рассчитываем взвешенные степени
for i in range(SIZE):
source_sum[i] = 0
target_sum[i] = 0
for j in range(SIZE):
# в исходном представлении надо не забыть заменить ненулевые веса единицей
source_sum[i] += 1 if source[i][j] > 0 else 0
target_sum[i] += target[i][j]
permutations = list(itertools.permutations([0, 1, 2, 3, 4, 5, 6]))
for permutation in permutations:
process_permutation(permutation)
На выходе получим:
Г Б В А К Д Е
46
Пример 6
Р-04. Между населёнными пунктами A, B, C, D, E, F, G построены дороги, протяжённость которых приведена в таблице. (Отсутствие числа в таблице означает, что прямой дороги между пунктами нет.)
Определите длину кратчайшего пути между пунктами A и G (при условии, что передвигаться можно только по построенным дорогам).
- Java
- C++
- Python
public class Example8 {
// названия вершин
static char[] names = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
// кол-во вершин графа
static int SIZE = 7;
// A B C D E F G
static int[][] m = new int[][]{
{0, 5, 0, 12, 0, 0, 25}, // A
{5, 0, 0, 8, 0, 0, 0}, // B
{0, 0, 0, 2, 4, 5, 10}, // C
{12, 8, 2, 0, 0, 0, 0}, // D
{0, 0, 4, 0, 0, 0, 5}, // E
{0, 0, 5, 0, 0, 0, 5}, // F
{25, 0, 10, 0, 5, 5, 0}, // G
};
static int findMinDistance(int start, int end) {
// заполняем расстояния от начальной вершины до рассматриваемой значениями -1
int[] distances = new int[SIZE];
Arrays.fill(distances,-1);
// начинаем с точки Б, поэтому индекс 1
int currentPoint = start;
// расстояние от точки до самой себя равно нулю
distances[currentPoint] = 0;
// массив флагов, закончена ли проверка для заданной точки
boolean[] complete = new boolean[SIZE];
// пока есть следующая точка
while (currentPoint != -1) {
// перебираем все вершины
for (int i = 0; i < SIZE; i++) {
if (i == currentPoint || complete[i])
continue;
// если у текущей есть с ней ребро
if (m[currentPoint][i] > 0) {
// если мы не обрабатывали вершину или новое расстояние через рассматриваемую вершину выше
if (distances[i] == -1 || distances[i] > distances[currentPoint] + m[currentPoint][i]) {
// рассчитываем новое расстояние, как сумму длины пути до текущей вершины
// и ребра от текущей вершины до заданной
distances[i] = distances[currentPoint] + m[currentPoint][i];
}
}
}
complete[currentPoint] = true;
// ищем следующую точку
int nextPoint = -1;
for (int i = 0; i < SIZE; i++) {
// если обработка точки не завершена
if (!complete[i])
// если мы уже доходили до точки и следующая точка ещё не задана или
// новое расстояние меньше
if (distances[i] > 0 && (nextPoint == -1 || distances[i] < distances[nextPoint])) {
nextPoint = i;
}
}
// переходим к следующей точке
currentPoint = nextPoint;
}
return distances[end];
}
public static void main(String[] args) {
System.out.println(findMinDistance(0, 6));
}
}
#include <algorithm>
#include <bits/stdc++.h>
// кол-во вершин (используется для удобства)
const int SIZE = 7;
// П1 П2 П3 П4 П5 П6 П7
const int m[SIZE][SIZE] = {
{0, 5, 0, 12, 0, 0, 25}, // A
{5, 0, 0, 8, 0, 0, 0}, // B
{0, 0, 0, 2, 4, 5, 10}, // C
{12, 8, 2, 0, 0, 0, 0}, // D
{0, 0, 4, 0, 0, 0, 5}, // E
{0, 0, 5, 0, 0, 0, 5}, // F
{25, 0, 10, 0, 5, 5, 0}, // G
};
// поиск кратчайшего пути
int findMinDistance(int start, int end) {
// заполняем расстояния от начальной вершины до рассматриваемой значениями -1
int distances[SIZE];
std::fill(std::begin(distances),std::begin(distances)+SIZE,-1);
// упорядоченное множество, в котором будут лежать индексы вершин графа, которые
// начинаем с точки Б, поэтому индекс 1
int currentPoint = start;
// расстояние от точки до самой себя равно нулю
distances[currentPoint] = 0;
// массив флагов, закончена ли проверка для заданной точки, изначально все элементы false
bool complete[SIZE];
std::fill(std::begin(complete),std::begin(complete)+SIZE, false);
// пока есть следующая точка
while (currentPoint != -1) {
// перебираем все вершины
for (int i = 0; i < SIZE; i++) {
if (i == currentPoint || complete[i])
continue;
// если у текущей есть с ней ребро
if (m[currentPoint][i] > 0) {
// если мы не обрабатывали вершину или новое расстояние через рассматриваемую вершину выше
if (distances[i] == -1 || distances[i] > distances[currentPoint] + m[currentPoint][i]) {
// рассчитываем новое расстояние, как сумму длины пути до текущей вершины
// и ребра от текущей вершины до заданной
distances[i] = distances[currentPoint] + m[currentPoint][i];
}
}
}
complete[currentPoint] = true;
// ищем следующую точку
int nextPoint = -1;
for (int i = 0; i < SIZE; i++) {
// если обработка точки не завершена
if (!complete[i])
// если мы уже доходили до точки и следующая точка ещё не задана или
// новое расстояние меньше
if (distances[i] > 0 && (nextPoint == -1 || distances[i] < distances[nextPoint]))
nextPoint = i;
}
// переходим к следующей точке
currentPoint = nextPoint;
}
return distances[end];
}
// главный метод программы
int main() {
// выводим ответ
std::cout << findMinDistance(0,6);
}
# кол - во вершин графа
SIZE = 7
m = [
[0, 5, 0, 12, 0, 0, 25], # A
[5, 0, 0, 8, 0, 0, 0], # B
[0, 0, 0, 2, 4, 5, 10], # C
[12, 8, 2, 0, 0, 0, 0], # D
[0, 0, 4, 0, 0, 0, 5], # E
[0, 0, 5, 0, 0, 0, 5], # F
[25, 0, 10, 0, 5, 5, 0], # G
]
# поиск кратчайшего пути
def findMinDistance(start, end):
# заполняем расстояния от начальной вершины до рассматриваемой значениями -1
distances = [-1] * SIZE
# упорядоченное множество, в котором будут лежать индексы вершин графа, которые
# начинаем с точки Б, поэтому индекс 1
currentPoint = start
# расстояние от точки до самой себя равно нулю
distances[currentPoint] = 0
# массив флагов, закончена ли проверка для заданной точки
complete = [False] * SIZE
# пока есть следующая точка
while currentPoint != -1:
# перебираем все вершины
for i in range(SIZE):
if i == currentPoint or complete[i]:
continue
# если у текущей есть с ней ребро
if m[currentPoint][i] > 0:
# если мы не обрабатывали вершину или новое расстояние через рассматриваемую вершину выше
if distances[i] == -1 or distances[i] > distances[currentPoint] + m[currentPoint][i]:
# рассчитываем новое расстояние, как сумму длины пути до текущей вершины
# и ребра от текущей вершины до заданной
distances[i] = distances[currentPoint] + m[currentPoint][i]
complete[currentPoint] = True
# ищем следующую точку
nextPoint = -1
for i in range(SIZE):
# если обработка точки не завершена
if not complete[i]:
# если мы уже доходили до точки и следующая точка ещё не задана или
# новое расстояние меньше
if distances[i] > 0 and (nextPoint == -1 or distances[i] < distances[nextPoint]):
nextPoint = i
# переходим к следующей точке
currentPoint = nextPoint
return distances[end]
# главный метод программы
if __name__ == '__main__':
print(findMinDistance(0, 6))
На выходе получим:
23
Пример 7
Р-03. Между населёнными пунктами A, B, C, D, E, F построены дороги, протяжённость которых приведена в таблице. (Отсутствие числа в таблице означает, что прямой дороги между пунктами нет.)
Определите длину кратчайшего пути между пунктами A и F (при условии, что передвигаться
можно только по построенным дорогам).
- Java
- C++
- Python
public class Example9 {
// названия вершин
static char[] names = {'A', 'B', 'C', 'D', 'E', 'F'};
// кол-во вершин графа
static int SIZE = 6;
// A B C D E F
static int[][] m = new int[][]{
{0, 2, 4, 0, 0, 0}, // A
{2, 0, 1, 0, 7, 0}, // B
{4, 1, 0, 3, 4, 0}, // C
{0, 0, 3, 0, 3, 0}, // D
{0, 7, 4, 3, 0, 2}, // E
{0, 0, 0, 0, 2, 0}, // F
};
static int findMinDistance(int start, int end) {
// заполняем расстояния от начальной вершины до рассматриваемой значениями -1
int[] distances = new int[SIZE];
Arrays.fill(distances,-1);
// начинаем с точки Б, поэтому индекс 1
int currentPoint = start;
// расстояние от точки до самой себя равно нулю
distances[currentPoint] = 0;
// массив флагов, закончена ли проверка для заданной точки
boolean[] complete = new boolean[SIZE];
// пока есть следующая точка
while (currentPoint != -1) {
// перебираем все вершины
for (int i = 0; i < SIZE; i++) {
if (i == currentPoint || complete[i])
continue;
// если у текущей есть с ней ребро
if (m[currentPoint][i] > 0) {
// если мы не обрабатывали вершину или новое расстояние через рассматриваемую вершину выше
if (distances[i] == -1 || distances[i] > distances[currentPoint] + m[currentPoint][i]) {
// рассчитываем новое расстояние, как сумму длины пути до текущей вершины
// и ребра от текущей вершины до заданной
distances[i] = distances[currentPoint] + m[currentPoint][i];
}
}
}
complete[currentPoint] = true;
// ищем следующую точку
int nextPoint = -1;
for (int i = 0; i < SIZE; i++) {
// если обработка точки не завершена
if (!complete[i])
// если мы уже доходили до точки и следующая точка ещё не задана или
// новое расстояние меньше
if (distances[i] > 0 && (nextPoint == -1 || distances[i] < distances[nextPoint])) {
nextPoint = i;
}
}
// переходим к следующей точке
currentPoint = nextPoint;
}
return distances[end];
}
public static void main(String[] args) {
System.out.println(findMinDistance(0, 5));
}
}
#include <algorithm>
#include <bits/stdc++.h>
// кол-во вершин (используется для удобства)
const int SIZE = 6;
// П1 П2 П3 П4 П5 П6 П7
const int m[SIZE][SIZE] = {
{0, 2, 4, 0, 0, 0}, // A
{2, 0, 1, 0, 7, 0}, // B
{4, 1, 0, 3, 4, 0}, // C
{0, 0, 3, 0, 3, 0}, // D
{0, 7, 4, 3, 0, 2}, // E
{0, 0, 0, 0, 2, 0}, // F
};
// поиск кратчайшего пути
int findMinDistance(int start, int end) {
// заполняем расстояния от начальной вершины до рассматриваемой значениями -1
int distances[SIZE];
std::fill(std::begin(distances),std::begin(distances)+SIZE,-1);
// упорядоченное множество, в котором будут лежать индексы вершин графа, которые
// начинаем с точки Б, поэтому индекс 1
int currentPoint = start;
// расстояние от точки до самой себя равно нулю
distances[currentPoint] = 0;
// массив флагов, закончена ли проверка для заданной точки, изначально все элементы false
bool complete[SIZE];
std::fill(std::begin(complete),std::begin(complete)+SIZE, false);
// пока есть следующая точка
while (currentPoint != -1) {
// перебираем все вершины
for (int i = 0; i < SIZE; i++) {
if (i == currentPoint || complete[i])
continue;
// если у текущей есть с ней ребро
if (m[currentPoint][i] > 0) {
// если мы не обрабатывали вершину или новое расстояние через рассматриваемую вершину выше
if (distances[i] == -1 || distances[i] > distances[currentPoint] + m[currentPoint][i]) {
// рассчитываем новое расстояние, как сумму длины пути до текущей вершины
// и ребра от текущей вершины до заданной
distances[i] = distances[currentPoint] + m[currentPoint][i];
}
}
}
complete[currentPoint] = true;
// ищем следующую точку
int nextPoint = -1;
for (int i = 0; i < SIZE; i++) {
// если обработка точки не завершена
if (!complete[i])
// если мы уже доходили до точки и следующая точка ещё не задана или
// новое расстояние меньше
if (distances[i] > 0 && (nextPoint == -1 || distances[i] < distances[nextPoint]))
nextPoint = i;
}
// переходим к следующей точке
currentPoint = nextPoint;
}
return distances[end];
}
// главный метод программы
int main() {
// выводим ответ
std::cout << findMinDistance(0,5);
}
# кол - во вершин графа
SIZE = 6
m = [
[0, 2, 4, 0, 0, 0], # A
[2, 0, 1, 0, 7, 0], # B
[4, 1, 0, 3, 4, 0], # C
[0, 0, 3, 0, 3, 0], # D
[0, 7, 4, 3, 0, 2], # E
[0, 0, 0, 0, 2, 0], # F
]
# поиск кратчайшего пути
def findMinDistance(start, end):
# заполняем расстояния от начальной вершины до рассматриваемой значениями -1
distances = [-1] * SIZE
# упорядоченное множество, в котором будут лежать индексы вершин графа, которые
# начинаем с точки Б, поэтому индекс 1
currentPoint = start
# расстояние от точки до самой себя равно нулю
distances[currentPoint] = 0
# массив флагов, закончена ли проверка для заданной точки
complete = [False] * SIZE
# пока есть следующая точка
while currentPoint != -1:
# print("current: " , currentPoint, " " , names[currentPoint])
# print(distances)
# перебираем все вершины
for i in range(SIZE):
if i == currentPoint or complete[i]:
continue
# если у текущей есть с ней ребро
if m[currentPoint][i] > 0:
# если мы не обрабатывали вершину или новое расстояние через рассматриваемую вершину выше
if distances[i] == -1 or distances[i] > distances[currentPoint] + m[currentPoint][i]:
# рассчитываем новое расстояние, как сумму длины пути до текущей вершины
# и ребра от текущей вершины до заданной
distances[i] = distances[currentPoint] + m[currentPoint][i]
complete[currentPoint] = True
# ищем следующую точку
nextPoint = -1
for i in range(SIZE):
# если обработка точки не завершена
if not complete[i]:
# если мы уже доходили до точки и следующая точка ещё не задана или
# новое расстояние меньше
if distances[i] > 0 and (nextPoint == -1 or distances[i] < distances[nextPoint]):
nextPoint = i
# переходим к следующей точке
currentPoint = nextPoint
return distances[end]
# главный метод программы
if __name__ == '__main__':
print(findMinDistance(0, 5))
На выходе получим:
9