Вы находитесь на странице: 1из 5

Билет № 08

1 Работа с матрицами (сложение, умножение, транспонирование). ( Постановка задачи,


входные данные, алгоритм, временные асимптотические оценки).

Определение матрицы
Матрица – это прямоугольная таблица элементов. Ну а если простым языком – таблица
чисел.

Обычно матрицы обозначаются прописными латинскими буквами. Например, матрица A,


матрица B и так далее. Матрицы могут быть разного размера: прямоугольные,
квадратные, также есть матрицы-строки и матрицы-столбцы, называемые векторами.
Размер матрицы определяется количеством строк и столбцов. Например, запишем
прямоугольную матрицу размера m на n, где m – количество строк, а n – количество
столбцов.

мтарицы, основные определения

Элементы, для которых i=j (a11, a22, .. ) образуют главную диагональ матрицы, и
называются диагональными.

Что можно делать с матрицами? Складывать/вычитать, умножать на число, умножать


между собой, транспонировать. Теперь обо всех этих основных операциях над матрицами
по порядку.

Операции сложения и вычитания матриц


Сразу предупредим, что можно складывать только матрицы одинакового размера. В
результате получится матрица того же размера. Складывать (или вычитать) матрицы
просто – достаточно только сложить их соответствующие элементы. Приведем пример.
Выполним сложение двух матриц A и В размером два на два.

Вычитание выполняется по аналогии, только с противоположным знаком.

Умножение матрицы на число


На произвольное число можно умножить любую матрицу. Чтобы сделать это, нужно
умножить на это число каждый ее элемент. Например, умножим матрицу A из первого
примера на число 5:

Умножение матрицы на число

Операция умножения матриц


Перемножить между собой удастся не все матрицы. Например, у нас есть две матрицы -
A и B. Их можно умножить друг на друга только в том случае, если число столбцов
матрицы А равно числу строк матрицы В. При этом каждый элемент получившейся
матрицы, стоящий в i-ой строке и j-м столбце, будет равен сумме произведений
соответствующих элементов в i-й строке первого множителя и j-м столбце второго.
Чтобы понять этот алгоритм, запишем, как умножаются две квадратные матрицы:

Умножение матриц

И пример с реальными числами. Умножим матрицы:

Умножение матриц пример

Операция транспонирования матрицы


Транспонирование матрицы – это операция, когда соответствующие строки и столбцы
меняются местами. Например, транспонируем матрицу A из первого примера:
Транспонирование матриц

Определитель матрицы
Определитель, о же детерминант – одно из основных понятий линейной алгебры. Когда-
то люди придумали линейные уравнения, а за ними пришлось выдумать и определитель. В
итоге, разбираться со всем этим предстоит вам, так что, последний рывок!

Определитель – это численная характеристика квадратной матрицы, которая нужна для


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

Определитель матрицы первого порядка, то есть состоящей из одного элемента, равен


этому элементу.

А если матрица три на три? Тут уже посложнее, но справиться можно.

Для такой матрицы значение определителя равно сумме произведений элементов главной
диагонали и произведений элементов лежащих на треугольниках с гранью параллельной
главной диагонали, от которой вычитается произведение элементов побочной диагонали
и произведение элементов лежащих на треугольниках с гранью параллельной побочной
диагонали.

К счастью, вычислять определители матриц больших размеров на практике приходится


редко.

Здесь мы рассмотрели основные операции над матрицами. Конечно, в реальной жизни


можно ни разу так и не встретить даже намека на матричную систему уравнений или же
наоборот - столкнуться с гораздо более сложными случаями, когда придется
действительно поломать голову. Именно для таких случаев и существует
профессиональный студенческий сервис. Обращайтесь за помощью, получайте
качественное и подробное решение, наслаждайтесь успехами в учебе и свободным
временем.

2 Алгоритмы поиска кратчайшего пути в лабиринте. ( Постановка задачи, входные


данные, алгоритмы, временные асимптотические оценки).

Все алгоритмы, применяемые для нахождения кратчайшего пути можно разделить на два
типа: алгоритмы на графах и алгоритмы на массивах.

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

Существуют три наиболее эффективных алгоритма нахождения кратчайшего пути на графе:

1) алгоритм Дейкстры. Используется для нахождения оптимального маршрута между двумя


вершинами.

2) алгоритм Флойда. Используется для нахождения оптимального маршрута между всеми


парами вершин.

3) алгоритм Йена. Используется для нахождения k-оптимальных маршрутов между двумя


вершинами.
Самый распространенный пример подобных задач, это нахождение кратчайшего расстояния
между двумя вершинами. В этом случае, весом дуги (хi, хj) будет являться расстояние
между вершинами хi и хj, ну, а если такая дуга отсутствует, то ее вес полагается
равным бесконечности (на практике - это максимальное число, возможное на данном
языке программирования).

Наиболее эффективный алгоритм решения задачи о кратчайшем (s-t)-пути первоначально


предложил Дейкстра (1959г.). В общем случае этот метод основан на приписывании
вершинам временных пометок, причем пометка вершины дает верхнюю границу длины от s
к этой вершине. Эти пометки (их величины) постепенно уменьшаются с помощью
некоторой итерационной процедуры, и на каждом шаге итерации одна из временных
пометок становится постоянной. Последнее указывает на то, что пометка уже не
является временной, а дает точную длину кратчайшего пути от s к рассматриваемой
вершине.

Только что описанный алгоритм Дейкстры применим для нахождения кратчайшего пути
между двумя заданными вершинами s и t. Что бы найти кратчайшие пути между всеми
парами вершин, можно n-раз воспользоваться алгоритмом Дейкстры, причем каждый раз в
качестве начальной вершины s будут браться различные вершины. В этом случае время,
необходимое для вычислений, будет пропорционально n3. Поэтому, если задача о
нахождении кратчайшего пути имеет большую размерность, то ее не возможно решить с
помощью последовательного применения этого алгоритма.

Есть совершенно иной подход к задаче нахождения кратчайших путей между всеми парами
вершин. Он сэкономит почти 50% времени по сравнению с n-кратным применением
алгоритма Дейкстры. Метод был предложен первоначально Флойдом (1962 г.) и развит
Мерчлендом. Он базируется на использовании последовательности из n преобразований
(итераций) начальной матрицы весов С. При этом на k-й итерации матрица представляет
длины кратчайших путей между каждой парой вершин с тем ограничением, что путь между
xi и xj (для любых xi и xj) содержит в качестве промежуточных только вершины из
множества {x1, x2,..., xk}.

На практике часто требуется найти не только кратчайший путь, но также второй,


третий и т. д. кратчайшие пути в графе. Располагая этими результатами, можно
решить, какой путь выбрать в качестве наилучшего. Для решения этой задачи нужно
воспользоваться алгоритмом Йена (1971г.). Этот алгоритм требует порядка Kn3
операций.

Существует тип алгоритмов, который в американской литературе фигурирует под


названием backtracking algorithms, что в переводе означает “алгоритмы с откатом”.
Как правило, такие алгоритмы строятся на основе рекурсии. Эти алгоритмы отличаются
от других тем, что ищут решения методом проб и ошибок, перебирая все или почти все
варианты.

Для начала разберемся с входными данными: у нас есть матрица элементов, где 0 —
пустые клетки, а 1 — стенки.
При вводе меняем «1» на "-1" (этого требует алгоритм)
Далее нужно выбрать ячейку, с которой начнется обход
Рекурсивно обойти лабиринт от выбранной ячейки, вставляя в ячейку текущий «уровень
волны»

Ввод данных будет выглядеть следующим образом:

rdl = list(map(int,input().split()))
n, m = rdl
for i in range(n):
rdl = input()
cur = []
for k in range(m):
if int(rdl[k]) == 1:
cur.append(-1)
else:
cur.append(int(rdl[k]))
lab.append(cur)

Теперь у нас есть двумерная матрица, представляющая наш лабиринт.


Далее нам нужно написать функцию, которая будет обходить наш лабиринт:

def voln(x, y, cur, n, m, lab):

Где x, y — координаты текущей ячейки; cur — «уровень волны»; n, m — размеры


лабиринта; lab — сам лабиринт.
Для начало нужно заполнить текущую ячейку уровнем воды:

lab[x][y] = cur

Далее проверим, есть ли у нас возможность «пойти» влево:

if y+1 < m:

Если есть такая возможность, то проверяем, нет ли там стенки или текущий «уровень
воды» меньше, чем в ячейке справа :

if lab[x][y+1] == 0 or (lab[x][y+1] != -1 and lab[x][y+1] > cur):

И в случае «успеха» рекурсивно идем вправо:

voln(x,y+1,cur+1,n,m,lab)

Теперь нужно точно также проверить возможность пройти вниз, влево и вверх:

if x+1<n:
if lab[x+1][y] == 0 or (lab[x+1][y] != -1 and lab[x+1][y] > cur):
voln(x+1,y,cur+1,n,m)
if x-1>=0:
if lab[x-1][y] == 0 or (lab[x-1][y] != -1 and lab[x-1][y] > cur):
voln(x-1,y,cur+1,n,m)
if y-1>=0:
if lab[x][y-1] == 0 or (lab[x][y-1] != -1 and lab[x][y-1] > cur):
voln(x,y-1,cur+1,n,m)

Все, осталось в конце вернуть текущий лабиринт:

return lab

Готовая программа:

def main():
lab = []
rdl = list(map(int,input().split()))
n, m = rdl
for i in range(n):
rdl = input()
cur = []
for k in range(m):
if int(rdl[k]) == 1:
cur.append(-1)
else:
cur.append(int(rdl[k]))
lab.append(cur)
rdl = list(map(int,input().split()))
x1, y1 = rdl[0]-1, rdl[1]-1
rdl = list(map(int,input().split()))
x2, y2 = rdl[0]-1, rdl[1] -1
lab = voln(x1,y1,1,n,m,lab)
if lab[x2][y2] > 0:
print("Mozhet")
else:
print("Ne mozhet")
def voln(x,y,cur,n,m):
lab[x][y] = cur
if y+1<m:
if lab[x][y+1] == 0 or (lab[x][y+1] != -1 and lab[x][y+1] > cur):
voln(x,y+1,cur+1,n,m,lab)
if x+1<n:
if lab[x+1][y] == 0 or (lab[x+1][y] != -1 and lab[x+1][y] > cur):
voln(x+1,y,cur+1,n,m,lab)
if x-1>=0:
if lab[x-1][y] == 0 or (lab[x-1][y] != -1 and lab[x-1][y] > cur):
voln(x-1,y,cur+1,n,m,lab)
if y-1>=0:
if lab[x][y-1] == 0 or (lab[x][y-1] != -1 and lab[x][y-1] > cur):
voln(x,y-1,cur+1,n,m,lab)
return lab
main()

Вам также может понравиться